Setelah mengaktifkan peringatan ketat di PHP 5.2, saya melihat banyak peringatan standar ketat dari proyek yang awalnya ditulis tanpa peringatan ketat:
Standar Ketat : Static function Program :: getSelectSQL () tidak boleh abstrak di Program.class.inc
Fungsi yang dimaksud adalah milik Program kelas induk abstrak dan dinyatakan statis abstrak karena harus diimplementasikan dalam kelas anaknya, seperti TVProgram.
Saya menemukan referensi untuk perubahan ini di sini :
Menghilangkan fungsi kelas statis abstrak. Karena pengawasan, PHP 5.0.x dan 5.1.x mengizinkan fungsi statis abstrak di kelas. Pada PHP 5.2.x, hanya antarmuka yang dapat memilikinya.
Pertanyaan saya adalah: dapatkah seseorang menjelaskan dengan jelas mengapa seharusnya tidak ada fungsi statis abstrak di PHP?
Jawaban:
metode statis milik kelas yang mendeklarasikannya. Saat memperluas kelas, Anda dapat membuat metode statis dengan nama yang sama, tetapi sebenarnya Anda tidak mengimplementasikan metode abstrak statis.
Hal yang sama berlaku untuk memperluas kelas apa pun dengan metode statis. Jika Anda memperluas kelas itu dan membuat metode statis dari tanda tangan yang sama, Anda sebenarnya tidak menimpa metode statis superclass
EDIT (16 September 2009)
Pembaruan tentang ini. Menjalankan PHP 5.3, saya melihat statis abstrak kembali, baik atau buruk. (lihat http://php.net/lsb untuk info lebih lanjut)
KOREKSI (oleh philfreo)
abstract static
masih tidak diperbolehkan di PHP 5.3, LSB terkait tetapi berbeda.sumber
abstract static
mungkin berguna dalam kasus ini.Ini cerita yang panjang dan menyedihkan.
Ketika PHP 5.2 pertama kali memperkenalkan peringatan ini, binding statis terbaru belum ada dalam bahasa tersebut. Jika Anda tidak terbiasa dengan binding statis yang terlambat, perhatikan bahwa kode seperti ini tidak berfungsi seperti yang Anda harapkan:
Mengesampingkan peringatan mode ketat, kode di atas tidak berfungsi. The
self::bar()
panggilanfoo()
eksplisit mengacu padabar()
metodeParentClass
, bahkan ketikafoo()
disebut sebagai metodeChildClass
. Jika Anda mencoba menjalankan kode ini dengan mode ketat nonaktif, Anda akan melihat " Kesalahan fatal PHP: Tidak dapat memanggil metode abstrak ParentClass :: bar () ".Mengingat ini, metode statis abstrak di PHP 5.2 tidak berguna. The Seluruh titik menggunakan metode abstrak adalah bahwa Anda dapat menulis kode yang memanggil metode tanpa mengetahui apa implementasi itu akan menjadi menelepon - dan kemudian memberikan implementasi yang berbeda pada anak kelas yang berbeda. Tetapi karena PHP 5.2 tidak menawarkan cara yang bersih untuk menulis metode kelas induk yang memanggil metode statis kelas anak tempat ia dipanggil, penggunaan metode statis abstrak ini tidak dimungkinkan. Karenanya setiap penggunaan
abstract static
dalam PHP 5.2 adalah kode yang buruk, mungkin terinspirasi oleh kesalahpahaman tentang cara kerjaself
kata kunci. Sangat masuk akal untuk memberikan peringatan atas hal ini.Tapi kemudian PHP 5.3 datang ditambahkan dalam kemampuan untuk merujuk ke kelas di mana metode dipanggil melalui
static
kata kunci (tidak sepertiself
kata kunci, yang selalu mengacu pada kelas di mana metode itu didefinisikan ). Jika Anda mengubahself::bar()
kestatic::bar()
dalam contoh saya di atas, ini berfungsi dengan baik di PHP 5.3 dan di atasnya. Anda dapat membaca lebih lanjut tentangself
vsstatic
at New self vs. new static .Dengan kata kunci statis ditambahkan, argumen yang jelas untuk
abstract static
mengeluarkan peringatan telah hilang. Tujuan utama pengikatan statis akhir adalah untuk memungkinkan metode yang didefinisikan dalam kelas induk untuk memanggil metode statis yang akan didefinisikan dalam kelas anak; memungkinkan metode statis abstrak tampaknya masuk akal dan konsisten mengingat adanya binding statis terlambat.Anda masih bisa, saya kira, membuat alasan untuk menjaga peringatan itu. Misalnya, Anda dapat berargumen bahwa karena PHP memungkinkan Anda memanggil metode statis kelas abstrak, dalam contoh saya di atas (bahkan setelah memperbaikinya dengan menggantinya
self
denganstatic
) Anda mengekspos metode publikParentClass::foo()
yang rusak dan Anda tidak benar-benar ingin melakukannya. membuka. Menggunakan kelas non-statis - yaitu, membuat semua metode contoh metode dan membuat turunan dariParentClass
semua menjadi lajang atau sesuatu - akan menyelesaikan masalah ini, karenaParentClass
, menjadi abstrak, tidak dapat dipakai dan metode contoh tidak bisa disebut. Saya pikir argumen ini lemah (karena saya pikir mengeksposParentClass::foo()
bukan masalah besar dan menggunakan lajang daripada kelas statis sering kali tidak perlu bertele-tele dan jelek), tetapi Anda mungkin cukup tidak setuju - ini adalah panggilan yang agak subjektif.Jadi berdasarkan argumen ini, pengembang PHP menyimpan peringatan dalam bahasa, bukan?
Uh, tidak juga .
Laporan bug PHP 53081, ditautkan di atas, meminta peringatan untuk dihapus karena penambahan
static::foo()
konstruksi telah membuat metode statis abstrak menjadi wajar dan berguna. Rasmus Lerdorf (pencipta PHP) memulai dengan memberi label permintaan palsu dan melewati rantai panjang alasan yang buruk untuk mencoba membenarkan peringatan tersebut. Kemudian, akhirnya, pertukaran ini terjadi:Klaim Rasmus bahwa kode dalam contohnya "berfungsi dengan baik" adalah salah; seperti yang Anda ketahui, itu melontarkan peringatan mode ketat. Saya kira dia sedang menguji tanpa mode ketat dihidupkan. Terlepas dari itu, Rasmus yang bingung meninggalkan permintaan yang ditutup secara keliru sebagai "palsu".
Dan itulah mengapa peringatan itu masih dalam bahasa. Ini mungkin bukan penjelasan yang sepenuhnya memuaskan - Anda mungkin datang ke sini berharap ada pembenaran rasional dari peringatan itu. Sayangnya, di dunia nyata, terkadang pilihan lahir dari kesalahan duniawi dan penalaran yang buruk daripada dari pengambilan keputusan yang rasional. Ini hanyalah salah satu saat itu.
Untungnya, Nikita Popov telah menghapus peringatan dari bahasa di PHP 7 sebagai bagian dari PHP RFC: Reclassify E_STRICT notices . Pada akhirnya, kewarasan telah menang, dan begitu PHP 7 dirilis, kita semua dapat dengan senang hati menggunakannya
abstract static
tanpa menerima peringatan konyol ini.sumber
Ada solusi yang sangat sederhana untuk masalah ini, yang sebenarnya masuk akal dari sudut pandang desain. Seperti yang ditulis Jonathan:
Jadi, sebagai solusi Anda bisa melakukan ini:
Dan sekarang Anda memaksakan bahwa setiap kelas yang membuat subkelas MyFoo mengimplementasikan metode statis getInstance, dan metode getSomeData publik. Dan jika Anda tidak membuat subkelas MyFoo, Anda masih dapat mengimplementasikan iMyFoo untuk membuat kelas dengan fungsionalitas serupa.
sumber
static::
bisa bermanfaat.abstract static
metode, tanpa PHP menggerutu ....Saya tahu ini sudah tua tapi ....
Mengapa tidak melontarkan pengecualian metode statis kelas induk itu, dengan cara itu jika Anda tidak menimpanya, pengecualian akan terjadi.
sumber
Saya berpendapat bahwa kelas / antarmuka abstrak dapat dilihat sebagai kontrak antara programmer. Ini lebih berkaitan dengan bagaimana sesuatu harus terlihat / berperilaku seperti dan tidak mengimplementasikan fungsionalitas yang sebenarnya. Seperti yang terlihat di php5.0 dan 5.1.x, ini bukanlah hukum alam yang mencegah pengembang php melakukannya, tetapi dorongan untuk mengikuti pola desain OO lainnya dalam bahasa lain. Pada dasarnya ide-ide ini mencoba untuk mencegah perilaku yang tidak diharapkan, jika seseorang sudah terbiasa dengan bahasa lain.
sumber
Saya tidak melihat alasan untuk melarang fungsi abstrak statis. Argumen terbaik bahwa tidak ada alasan untuk melarangnya adalah, bahwa mereka diperbolehkan di Jawa. Pertanyaannya adalah: - Apakah secara teknis dapat dilakukan? - Ya, karena ada di PHP 5.2 dan ada di Java. Jadi, mana BISA melakukannya. HARUSkah kita melakukannya? - Apakah itu masuk akal? Iya. Masuk akal untuk mengimplementasikan bagian dari kelas dan menyerahkan bagian lain dari kelas kepada pengguna. Masuk akal dalam fungsi non-statis, mengapa tidak masuk akal untuk fungsi statis? Satu penggunaan fungsi statis adalah kelas di mana tidak boleh ada lebih dari satu instance (singletons). Misalnya mesin enkripsi. Ini tidak perlu ada dalam beberapa kasus dan ada alasan untuk mencegahnya - misalnya, Anda harus melindungi hanya satu bagian dari memori dari penyusup. Jadi sangat masuk akal untuk menerapkan satu bagian dari mesin dan menyerahkan algoritma enkripsi kepada pengguna. Ini hanya satu contoh. Jika Anda terbiasa menggunakan fungsi statis, Anda akan menemukan lebih banyak lagi.
sumber
Di php 5.4+ gunakan sifat:
dan di kelas Anda letakkan di awal:
sumber
abstract public static function get_table_name();
sifat dan menggunakan sifat itu dalam kelas abstrak saya tanpa peringatan E_STRICT lagi! Ini masih memaksakan pendefinisian metode statis pada anak-anak seperti yang saya harapkan. Fantastis!Perhatikan masalah 'Late Static Binding' PHP. Jika Anda menempatkan metode statis pada kelas abstrak, Anda mungkin akan menemukannya lebih cepat daripada nanti. Masuk akal jika peringatan ketat memberi tahu Anda untuk menghindari penggunaan fitur bahasa yang rusak.
sumber