Apa sebenarnya binding statis terlambat di PHP?
sumber
Anda pasti perlu membaca Late Static Bindings di manual PHP. Namun, saya akan mencoba memberi Anda ringkasan singkat.
Pada dasarnya, ini bermuara pada fakta bahwa self
kata kunci tidak mengikuti aturan pewarisan yang sama. self
selalu menetapkan kelas yang digunakan. Artinya jika Anda membuat metode di kelas induk dan memanggilnya dari kelas anak, self
tidak akan mereferensikan anak seperti yang Anda harapkan.
Pengikatan statis akhir memperkenalkan penggunaan baru untuk static
kata kunci, yang membahas kekurangan khusus ini. Saat Anda menggunakannya static
, ini mewakili kelas tempat Anda pertama kali menggunakannya, yaitu. itu 'mengikat' ke kelas runtime.
Itulah dua konsep dasar di baliknya. Cara self
, parent
dan static
pengoperasian saat static
sedang dimainkan bisa jadi tidak kentara, jadi daripada membahas lebih detail, saya sangat menyarankan Anda mempelajari contoh halaman manual. Setelah Anda memahami dasar-dasar setiap kata kunci, contoh sangat diperlukan untuk melihat hasil seperti apa yang akan Anda dapatkan.
self
kata kunci tidak mengikuti aturan pewarisan.self
selalu menentukan kelas penggunaannya." - Yang tidak berarti Anda tidak dapat memanggil metode statis induk dari objek anak melaluiself
, seperti metode non-statis. Anda mungkin bermaksud benar, tetapi Anda harus mengulanginya kembali. Itu semua hanya benar-benar penting setelah anak-anak memiliki nama anggota yang identik karena Anda kemudian dapat memutuskan mana yang akan dirujuk dengan menggunakanstatic::
sebagai gantinya.Dari PHP: Late Static Bindings - Manual :
Mari kita lihat contohnya:
<?php class Car { public static function run() { return static::getName(); } private static function getName() { return 'Car'; } } class Toyota extends Car { public static function getName() { return 'Toyota'; } } echo Car::run(); // Output: Car echo Toyota::run(); // Output: Toyota ?>
sumber
Tidak ada perilaku yang sangat jelas:
Kode berikut menghasilkan 'alphabeta'.
class alpha { function classname(){ return __CLASS__; } function selfname(){ return self::classname(); } function staticname(){ return static::classname(); } } class beta extends alpha { function classname(){ return __CLASS__; } } $beta = new beta(); echo $beta->selfname(); // Output: alpha echo $beta->staticname(); // Output: beta
Namun, jika kita menghapus deklarasi fungsi nama kelas dari kelas beta, kita mendapatkan 'alphaalpha' sebagai hasilnya.
sumber
Saya mengutip dari buku: "PHP Master menulis kode mutakhir".
Jangan ragu untuk melihat dokumentasi resmi php juga: http://php.net/manual/en/language.oop5.late-static-bindings.php
Cara paling jelas untuk menjelaskan Late Static Binding adalah dengan contoh sederhana. Perhatikan dua definisi kelas di bawah ini, dan baca terus.
class Vehicle { public static function invokeDriveByStatic() { return static::drive(); // Late Static Binding } public static function invokeStopBySelf() { return self::stop(); // NOT Late Static Binding } private static function drive(){ return "I'm driving a VEHICLE"; } private static function stop(){ return "I'm stopping a VEHICLE"; } } class Car extends Vehicle { protected static function drive(){ return "I'm driving a CAR"; } private static function stop(){ return "I'm stopping a CAR"; } }
Kami melihat Kelas Orang Tua (Kendaraan) dan Kelas Anak (Mobil). Kelas Parent memiliki 2 metode publik:
invokeDriveByStatic
invokeStopBySelf
Kelas Parent juga memiliki 2 metode privat:
drive
stop
Kelas Anak mengesampingkan 2 metode:
drive
stop
Sekarang mari panggil metode publik:
invokeDriveByStatic
invokeStopBySelf
Tanyakan pada diri Anda: Kelas mana yang meminta
invokeDriveByStatic
/invokeStopBySelf
? Kelas Orang Tua atau Anak?Lihat di bawah ini:
// This is NOT Late Static Binding // Parent class invokes from Parent. In this case Vehicle. echo Vehicle::invokeDriveByStatic(); // I'm driving a VEHICLE echo Vehicle::invokeStopBySelf(); // I'm stopping a VEHICLE // !!! This is Late Static Binding !!!! // Child class invokes an inherited method from Parent. // Child class = Car, Inherited method = invokeDriveByStatic(). // The inherited method invokes a method that is overridden by the Child class. // Overridden method = drive() echo Car::invokeDriveByStatic(); // I'm driving a CAR // This is NOT Late Static Binding // Child class invokes an inherited method from Parent. // The inherited method invokes a method inside the Vehicle context. echo Car::invokeStopBySelf(); // I'm stopping a VEHICLE
Kata
static
kunci digunakan dalam pola desain Singleton. Lihat tautan: https://refactoring.guru/design-patterns/singleton/php/examplesumber
Contoh paling sederhana untuk menunjukkan perbedaannya.
Catatan, diri :: $ c
class A { static $c = 7; public static function getVal() { return self::$c; } } class B extends A { static $c = 8; } B::getVal(); // 7
Pengikatan statis terlambat, perhatikan statis :: $ c
class A { static $c = 7; public static function getVal() { return static::$c; } } class B extends A { static $c = 8; } B::getVal(); // 8
sumber
Sebagai contoh:
abstract class Builder { public static function build() { return new static; } } class Member extends Builder { public function who_am_i() { echo 'Member'; } } Member::build()->who_am_i();
sumber
Melihatnya dari pertanyaan "mengapa saya menggunakan ini?" perspektif, ini pada dasarnya adalah cara untuk mengubah konteks dari mana metode statis sedang diinterpretasikan / dijalankan.
Dengan
self
, konteksnya adalah tempat Anda mendefinisikan metode aslinya. Denganstatic
, itu yang Anda panggil.sumber
Juga, perhatikan jika Anda memperbarui variabel statis di kelas anak. Saya menemukan ini (agak) hasil yang tidak terduga di mana anak B memperbarui anak C:
class A{ protected static $things; } class B extends A { public static function things(){ static::$things[1] = 'Thing B'; return static::$things; } } class C extends A{ public static function things(){ static::$things[2] = 'Thing C'; return static::$things; } } print_r(C::things()); // Array ( // [2] => Thing C // ) B::things(); print_r(C::things()); // Array ( // [2] => Thing C // [1] => Thing B // )
Anda dapat memperbaikinya dengan mendeklarasikan variabel yang sama di setiap kelas anak, misalnya:
class C extends A{ protected static $things; // add this and B will not interfere! public static function things(){ static::$things[2] = 'Thing C'; return static::$things; } }
sumber