Huraikan kaedah liputan subkelas PHP 7.2 yang meninggalkan fungsi jenis parameter dan prinsip penggantian Liskov
PHP 7.2 telah dikeluarkan untuk seketika, selagi anda mengambil berat tentang sebarang peningkatan baharu dalam versi baharu Anda sepatutnya telah melihat perkembangan PHP. Di sini saya hanya akan memperincikan satu ciri baharu yang mungkin disalah ertikan.
PHP 7.2 boleh mengabaikan jenis parameter (petunjuk jenis) yang ditakrifkan oleh kaedah kelas induk apabila subkelas mengatasi kaedah kelas induk:
class Foo { public function bar(SomeClass $obj) {} } class Foobar extends Foo { public function bar($obj) {} // 这在 PHP7.2 版本之前是会报错的 }
Saya melihat beberapa Apabila tapak web memperkenalkan ciri ini , ia mengatakan bahawa tujuannya adalah untuk memudahkan pemfaktoran semula. Jika jenis parameter kaedah kelas induk berubah pada masa hadapan, subkelas tidak perlu mengubah semuanya." Bunyinya munasabah. Menurut kenyataan ini, maksud tersirat ialah: jika subkelas mengabaikan jenis parameter kaedah kelas induk, jenis parameter masih akan disemak apabila ia dipanggil. Anda akan mengetahui situasi sebenar dengan melakukan percubaan ini:
<?php class Foo { } class Bar { public function setFoo(Foo $foo) { } } class BarKid extends Bar { public function setFoo($foo) { } } $kid = new BarKid; $kid->setFoo('I am a string!');
Jika pernyataan di atas betul, setFoo harus melaporkan ralat apabila ia menerima parameter rentetan Walau bagaimanapun, kod di atas tidak melaporkan sebarang ralat di bawah 7.2 maklumat, tetapi jika kaedah setFoo subkelas menambah jenis parameter, ralat akan dilaporkan serta-merta. Ingat bahawa banyak pendapat di Internet tidak boleh dipercayai, kecuali laman web saya yang kecil...
Percubaan di atas menunjukkan bahawa kaedah subkelas boleh menghilangkan jenis parameter, dan tujuannya pastinya bukan untuk memudahkan pemfaktoran semula. Jadi apa tujuan sebenarnya?
Terdapat ciri baharu dalam PHP 7.1, iaitu "Anda boleh menetapkan sama ada parameter dan jenis pengembalian kaedah atau fungsi boleh menjadi batal". Terdapat satu peraturan yang kelihatan agak janggal: "Julat jenis parameter kaedah subkelas dilonggarkan (iaitu, jika parameter kelas induk tidak boleh batal, parameter subkelas boleh menyokong nol), tetapi jenis pulangan diketatkan (jika kelas induk tidak boleh mengembalikan null, parameter subkelas boleh menyokong null). "Prinsip penggantian Liskov", tetapi tidak memperkenalkannya secara mendalam. Tidak ramai PHP di sekeliling saya memberi perhatian kepada prinsip OOP, tetapi saya fikir ia harus diketahui oleh setiap jurutera, jadi saya ingin memperkenalkannya.
Prinsip penggantian Liskov adalah mudah: di mana sahaja kelas induk muncul, ia boleh dijalankan jika digantikan dengan subkelas, iaitu subkelas boleh menggantikan kelas induk tanpa berfikir. Malah, dari sudut reka bentuk bahasa, saya rasa prinsip ini adalah tiruan peraturan semula jadi 2018-09-29 Tambahan: Ia bukan "tiruan" yang mudah, Jika anda berminat, anda boleh membaca blog baru "Penguin bukan Burung』.
Contohnya, orang boleh minum arak, minum teh, minum cola, dan minum pelbagai jenis minuman, tetapi sebagai mamalia, manusia boleh minum air tidak kira, bukan? Tetapi sebaliknya, mamalia boleh minum air, tetapi mereka mungkin tidak semestinya boleh minum alkohol, teh atau cola, jadi manusia adalah subkategori mamalia.
Dari perspektif reka bentuk bahasa, subkelas hendaklah versi dipertingkatkan bagi kelas induk, yang bermaksud ia seharusnya dapat mengendalikan lebih banyak jenis objek daripada kelas induk. Ini juga berlaku dengan pengembangan yang diganti jenis parameter kaedah Penjelmaan prinsip.
Mari kita bincangkan tentang jenis pemulangan, yang mungkin agak berbelit-belit Mengapakah subkelas perlu mengecilkan julat pemulangan? Malah, selagi anda menganggap bahawa pengembalian satu kaedah akan digunakan sebagai parameter kaedah lain, ia adalah mudah untuk difikirkan. Sebagai contoh, kelas "Kilang Minuman Buah-buahan" mempunyai kaedah "Pengeluaran" yang mengembalikan "Jus Buah-buahan" dan menyerahkannya kepada kaedah "Minum" "Kanak-kanak". Terdapat kelas "Kilang Jus Oren" yang merupakan subkelas "Kilang Minuman Buah-buahan". Jenis pulangan kaedah "Pengeluaran"nya disempitkan dan hanya boleh mengembalikan "Jus Oren" Ia masih diberikan kepada "kanak-kanak". minum" dan tidak akan muncul. Sebarang pertanyaan.
Berikan contoh balas yang lain. Jika subkelas lain "Kilang Minuman Buah" muncul, dan kaedah "Pengeluaran"nya boleh mengembalikan wain buah sebagai tambahan kepada jus buah, maka subkelas ini jelas tidak boleh menggantikan kelas induk yang berisiko diminum untuk kanak-kanak.
Selepas bercakap tentang prinsip penggantian Liskov, mari kita lihat peningkatan ini dalam 7.2. Kita harus tahu pada masa ini bahawa ini sebenarnya adalah manifestasi prinsip Liskov. Pada masa ini, pelaksanaan prinsip penggantian dalam PHP tidak lengkap. Sesetengah orang mungkin berfikir bahawa versi ini juga menyokong "kelas induk tidak mempunyai jenis pulangan, dan subkelas boleh mempunyai jenis pulangan"? Malangnya, sekurang-kurangnya dalam versi 7.2, ia tidak disokong Anda boleh mencuba sendiri.
Satu lagi ciri baharu dalam 7.2 ialah objek boleh digunakan sebagai jenis mana-mana objek. Lihat contoh rasmi:
<?php function test(object $obj) : object { return new SplQueue(); } test(new StdClass());
Malah, sebelum keluaran 7.2, juga berdasarkan prinsip penggantian, terdapat soalan tentang "sama ada subkelas boleh menggunakan jenis objek untuk menggantikan jenis kaedah yang diganti. parameter objek." Tetapi undian terakhir tidak lulus. Walaupun saya tidak tahu sebabnya, sekurang-kurangnya ada yang menyebutnya.
Selain itu, pada masa ini PHP tidak boleh membebankan seperti Java, dan tidak ada cara untuk menentukan jenis kaedah yang diganti (pada masa ini jenis itu hanya boleh dialih keluar secara langsung, yang agak terlalu kasar):
<?php class Foo { } class FooFoo extends Foo { } class Bar { public function foo(FooFoo $foo) { } } class BarBar extends Bar { public function foo(Foo $foo) // 依然会报『子类不兼容父类方法格式』的错误 { } }
Tetapi PHP sentiasa berubah, bukan? Versi PHP telah berulang dengan begitu pantas baru-baru ini, dan saya sangat yakin bahawa PHP akan menjadi bahasa yang menyokong lebih banyak ciri OOP!
Pembelajaran yang disyorkan: "Tutorial PHP7"
Atas ialah kandungan terperinci Analisis isu yang berkaitan dengan PHP7.2 mengabaikan kaedah kelas induk dan prinsip penggantian Liskov. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!