PHP adalah bahasa pemrograman pertama saya. Saya tidak bisa membungkus kepala saya kapan harus menggunakan kelas statis vs objek instantiated.
Saya menyadari bahwa Anda dapat menggandakan dan mengkloning objek. Namun dalam seluruh waktu saya menggunakan php, objek atau fungsi apa pun selalu berakhir sebagai nilai pengembalian (array, string, int) tunggal atau batal.
Saya memahami konsep dalam buku seperti kelas karakter video game. duplikat objek mobil dan buat yang baru merah , itu semua masuk akal, tetapi yang tidak adalah aplikasinya di php dan aplikasi web.
Contoh sederhana. Sebuah blog. Objek blog apa yang paling baik diimplementasikan sebagai objek statis atau instantiated? Kelas DB? Mengapa tidak hanya instantiate objek db dalam lingkup global? Mengapa tidak menjadikan setiap objek statis sebagai gantinya? Bagaimana dengan kinerja?
Apakah ini semua hanya gaya? Apakah ada cara yang tepat untuk melakukan hal ini?
Dua alasan utama untuk tidak menggunakan metode statis adalah:
Memiliki panggilan metode statis di dalam beberapa metode lain sebenarnya lebih buruk daripada mengimpor variabel global. Di PHP, kelas adalah simbol global, jadi setiap kali Anda memanggil metode statis, Anda mengandalkan simbol global (nama kelas). Ini adalah kasus ketika global itu jahat. Saya punya masalah dengan pendekatan semacam ini dengan beberapa komponen Zend Framework. Ada kelas yang menggunakan pemanggilan metode statis (pabrik) untuk membangun objek. Tidak mungkin bagi saya untuk memasok pabrik lain ke instance itu untuk mendapatkan objek yang disesuaikan dikembalikan. Solusi untuk masalah ini adalah dengan hanya menggunakan instance dan metode instace dan menegakkan lajang dan sejenisnya di awal program.
Miško Hevery , yang bekerja sebagai Agile Coach di Google, memiliki teori yang menarik, atau lebih tepatnya menyarankan, bahwa kita harus memisahkan waktu pembuatan objek dari saat kita menggunakan objek. Jadi siklus hidup suatu program terbagi dua. Bagian pertama (
main()
metode katakanlah), yang menangani semua objek pengkabelan dalam aplikasi Anda dan bagian yang melakukan pekerjaan yang sebenarnya.Jadi alih-alih memiliki:
Kita sebaiknya melakukan:
Dan kemudian, di halaman indeks / utama, kami akan melakukan (ini adalah langkah pengkabelan objek, atau waktu untuk membuat grafik instance yang akan digunakan oleh program):
Gagasan utamanya adalah memisahkan ketergantungan dari kelas Anda. Dengan cara ini, kode ini jauh lebih mudah dikembangkan dan, bagian terpenting bagi saya, dapat diuji. Mengapa lebih penting untuk diuji? Karena saya tidak selalu menulis kode perpustakaan, jadi ekstensibilitas tidak terlalu penting, tetapi testabilitas penting ketika saya melakukan refactoring. Bagaimanapun, kode yang dapat diuji biasanya menghasilkan kode yang dapat diperluas, jadi ini bukan benar-benar situasi yang baik.
Miško Hevery juga membuat perbedaan yang jelas antara lajang dan lajang (dengan atau tanpa huruf kapital S). Perbedaannya sangat sederhana. Lajang dengan huruf "s" kecil diberlakukan oleh kabel di indeks / utama. Anda instantiate objek kelas yang tidak menerapkan pola Singleton dan berhati-hati bahwa Anda hanya meneruskan instance itu ke instance lain yang membutuhkannya. Di sisi lain, Singleton, dengan huruf kapital "S" adalah implementasi dari pola klasik (anti-). Pada dasarnya global yang menyamar yang tidak banyak digunakan di dunia PHP. Saya belum melihat satu sampai saat ini. Jika Anda ingin koneksi DB tunggal digunakan oleh semua kelas Anda lebih baik melakukannya seperti ini:
Dengan melakukan hal di atas, jelas bahwa kita memiliki seorang wanita lajang dan kita juga memiliki cara yang baik untuk menyuntikkan mock atau stub dalam tes kita. Mengejutkan bahwa unit test menghasilkan desain yang lebih baik. Tetapi masuk akal jika Anda berpikir bahwa tes memaksa Anda untuk berpikir tentang cara Anda menggunakan kode itu.
Satu-satunya situasi di mana saya akan menggunakan (dan saya telah menggunakannya untuk meniru objek prototipe JavaScript di PHP 5.3) anggota statis adalah ketika saya tahu bahwa masing-masing bidang akan memiliki nilai yang sama contoh lintas. Pada titik itu Anda dapat menggunakan properti statis dan mungkin sepasang metode pengambil / penyetel statis. Bagaimanapun, jangan lupa untuk menambahkan kemungkinan untuk menimpa anggota statis dengan anggota contoh. Misalnya Zend Framework menggunakan properti statis untuk menentukan nama kelas adaptor DB yang digunakan dalam contoh
Zend_Db_Table
. Sudah beberapa saat sejak saya menggunakannya sehingga mungkin tidak lagi relevan, tapi itulah yang saya ingat.Metode statis yang tidak berurusan dengan properti statis haruslah berfungsi. PHP memiliki fungsi dan kita harus menggunakannya.
sumber
Jadi dalam PHP statis bisa diterapkan ke fungsi atau variabel. Variabel non-statis terkait dengan instance kelas tertentu. Metode non-statis bertindak atas instance kelas. Jadi mari kita membuat kelas yang disebut
BlogPost
.title
akan menjadi anggota yang tidak statis. Ini berisi judul posting blog itu. Kami mungkin juga memiliki metode yang disebutfind_related()
. Itu tidak statis karena memerlukan informasi dari instance tertentu dari kelas posting blog.Kelas ini akan terlihat seperti ini:
Di sisi lain, menggunakan fungsi statis, Anda dapat menulis kelas seperti ini:
Dalam hal ini, karena fungsinya statis dan tidak bekerja pada posting blog tertentu, Anda harus mengirimkan posting blog sebagai argumen.
Pada dasarnya ini adalah pertanyaan tentang desain berorientasi objek. Kelas-kelas Anda adalah kata benda dalam sistem Anda, dan fungsi-fungsi yang bekerja pada mereka adalah kata kerja. Fungsi statis bersifat prosedural. Anda meneruskan objek fungsi sebagai argumen.
Pembaruan: Saya juga menambahkan bahwa keputusan jarang antara metode instance dan metode statis, dan lebih banyak lagi antara menggunakan kelas dan menggunakan array asosiatif. Misalnya, dalam aplikasi blogging, Anda membaca posting blog dari database dan mengubahnya menjadi objek, atau membiarkannya dalam kumpulan hasil dan memperlakukannya sebagai array asosiatif. Kemudian Anda menulis fungsi yang menggunakan array asosiatif atau daftar array asosiatif sebagai argumen.
Dalam skenario OO, Anda menulis metode di
BlogPost
kelas Anda yang bertindak pada posting individu, dan Anda menulis metode statis yang bertindak pada kumpulan posting.sumber
Jauh, ya. Anda dapat menulis program berorientasi objek yang sangat baik tanpa menggunakan anggota statis. Bahkan beberapa orang akan berpendapat bahwa anggota statis adalah pengotor di tempat pertama. Saya akan menyarankan bahwa - sebagai pemula di oop - Anda mencoba untuk menghindari anggota statis bersama-sama. Ini akan memaksa Anda ke arah penulisan dalam gaya berorientasi objek daripada gaya prosedural .
sumber
Saya memiliki pendekatan berbeda untuk sebagian besar jawaban di sini, terutama ketika menggunakan PHP. Saya pikir semua kelas harus statis kecuali Anda punya alasan bagus mengapa tidak. Beberapa alasan "mengapa tidak" adalah:
Biarkan saya ambil satu contoh. Karena setiap skrip PHP menghasilkan kode HTML, kerangka kerja saya memiliki kelas penulis html. Ini memastikan bahwa tidak ada kelas lain yang akan mencoba menulis HTML karena itu adalah tugas khusus yang harus dikonsentrasikan ke dalam satu kelas.
Biasanya, Anda akan menggunakan kelas html seperti ini:
Setiap kali get_buffer () dipanggil, ia me-reset semuanya sehingga kelas berikutnya untuk menggunakan penulis html dimulai dalam keadaan yang dikenal.
Semua kelas statis saya memiliki fungsi init () yang perlu dipanggil sebelum kelas digunakan untuk pertama kalinya. Ini lebih dari konvensi daripada keharusan.
Alternatif untuk kelas statis dalam hal ini berantakan. Anda tidak ingin setiap kelas yang perlu menulis sedikit html harus mengelola instance dari penulis html.
Sekarang saya akan memberi Anda contoh kapan tidak menggunakan kelas statis. Kelas formulir saya mengelola daftar elemen formulir seperti input teks, daftar dropdown, dan lainnya. Biasanya digunakan seperti ini:
Tidak ada cara Anda bisa melakukan ini dengan kelas statis, terutama mengingat bahwa beberapa konstruktor dari setiap kelas tambahan melakukan banyak pekerjaan. Juga, rantai pewarisan untuk semua elemen cukup kompleks. Jadi ini adalah contoh yang jelas di mana kelas statis tidak boleh digunakan.
Sebagian besar kelas utilitas seperti yang mengonversi / memformat string adalah kandidat yang baik untuk menjadi kelas statis. Aturan saya sederhana: semuanya berjalan statis di PHP kecuali ada satu alasan mengapa tidak.
sumber
"Memiliki panggilan metode statis di dalam beberapa metode lain sebenarnya lebih buruk daripada mengimpor variabel global." (tentukan "lebih buruk") ... dan "Metode statis yang tidak berurusan dengan properti statis haruslah fungsi".
Keduanya adalah pernyataan yang cukup menyapu. Jika saya memiliki seperangkat fungsi yang terkait dalam materi pelajaran, tetapi data contoh benar-benar tidak sesuai, saya lebih suka mereka didefinisikan dalam kelas dan tidak masing-masing di ruang nama global. Saya hanya menggunakan mekanisme yang tersedia di PHP5 untuk
itu hanya cara yang nyaman untuk menegakkan kohesi yang lebih tinggi dan kopling yang lebih rendah.
Dan FWIW - tidak ada hal seperti itu, setidaknya di PHP5, sebagai "kelas statis"; metode dan properti bisa statis. Untuk mencegah instantiasi kelas, seseorang dapat mendeklarasikannya secara abstrak.
sumber
Pertama-tama tanyakan pada diri Anda, benda apa yang akan diwakili? Sebuah instance objek baik untuk beroperasi pada set data dinamis yang terpisah.
Contoh yang baik adalah ORM atau lapisan abstraksi basis data. Anda mungkin memiliki beberapa koneksi basis data.
Kedua koneksi sekarang dapat beroperasi secara independen:
Sekarang di dalam paket / pustaka ini, mungkin ada kelas lain seperti Db_Row, dll. Untuk mewakili baris tertentu yang dikembalikan dari pernyataan SELECT. Jika kelas Db_Row ini adalah kelas statis, maka itu akan mengasumsikan Anda hanya memiliki satu baris data dalam satu database dan tidak mungkin untuk melakukan apa yang bisa instance objek. Dengan sebuah instance, Anda sekarang dapat memiliki jumlah baris yang tidak terbatas dalam jumlah tabel yang tidak terbatas dalam jumlah database yang tidak terbatas. Satu-satunya batasan adalah perangkat keras server;).
Misalnya, jika metode getRows pada objek Db mengembalikan array objek Db_Row, Anda sekarang dapat beroperasi di setiap baris secara independen satu sama lain:
Contoh yang baik dari kelas statis adalah sesuatu yang menangani variabel registri, atau variabel sesi karena hanya akan ada satu registri atau satu sesi per pengguna.
Di salah satu bagian aplikasi Anda:
Dan di bagian lain:
Karena hanya akan ada satu pengguna pada satu waktu per sesi, tidak ada gunanya membuat contoh untuk Sesi.
Saya harap ini membantu, bersama dengan jawaban lain untuk membantu menjernihkan semuanya. Sebagai catatan tambahan, lihat " kohesi " dan " kopling ". Mereka menguraikan beberapa praktik yang sangat, sangat baik untuk digunakan saat menulis kode Anda yang berlaku untuk semua bahasa pemrograman.
sumber
Jika kelas Anda statis itu berarti Anda tidak bisa meneruskan objeknya ke kelas lain (karena tidak ada contoh yang memungkinkan) sehingga berarti semua kelas Anda akan langsung menggunakan kelas statis itu yang berarti kode Anda sekarang dipasangkan dengan kelas. .
Kopling ketat membuat kode Anda kurang dapat digunakan kembali, rapuh dan rentan terhadap bug. Anda ingin menghindari kelas statis agar dapat melewatkan instance kelas ke kelas lain.
Dan ya ini hanya satu dari banyak alasan lain yang beberapa di antaranya telah disebutkan.
sumber
Secara umum, Anda harus menggunakan variabel anggota dan fungsi anggota kecuali itu benar-benar harus dibagi antara semua contoh atau kecuali Anda membuat singleton. Menggunakan data anggota dan fungsi anggota memungkinkan Anda menggunakan kembali fungsi Anda untuk beberapa bagian data yang berbeda, sedangkan Anda hanya dapat memiliki satu salinan data tempat Anda beroperasi jika Anda menggunakan data dan fungsi statis. Selain itu, meskipun tidak berlaku untuk PHP, fungsi statis dan data menyebabkan kode menjadi non-reentrant, sedangkan data kelas memfasilitasi reentrancy.
sumber
Saya ingin mengatakan bahwa pasti ada kasus di mana saya ingin variabel statis - dalam aplikasi lintas bahasa. Anda dapat memiliki kelas tempat Anda menggunakan bahasa (mis. $ _SESSION ['language']) dan pada gilirannya mengakses kelas lain yang dirancang seperti ini:
Menggunakan Strings :: getString ("somestring") adalah cara yang bagus untuk abstrak penggunaan bahasa Anda dari aplikasi Anda. Anda bisa melakukannya sesuka Anda tetapi dalam kasus ini setiap file string memiliki konstanta dengan nilai string yang diakses oleh kelas Strings berfungsi dengan cukup baik.
sumber