Saya tidak mengatakan bahawa antara muka "mengubah tingkah laku kelas", saya mengatakan bahawa antara muka memudahkan untuk melanjutkan kefungsian kelas.
Untuk memahami antara muka, sebagai konsep pengaturcaraan berorientasikan objek, kita harus terlebih dahulu memahami masalah yang ingin diselesaikan.
Antara muka ialah kontrak. Begini cara untuk melaksanakan penaipan itik dalam PHP. Anda perlu berfikir dari perspektif penulis perpustakaan yang ingin mendedahkan fungsi kepada orang lain. Contohnya,
class Greeter { public function greet($person) { echo "Hello, {$person->getName()}!\n"; } }
Untuk memastikan pengguna perpustakaan mengetahui kaedah $person
需要有 getName()
方法,您可以創(chuàng)建一個類 Person
> 有一個 getName()
. Kemudian gunakan taip pengisytiharan untuk mengesan kemungkinan ralat apabila kod diselesaikan.
class Greeter { public function greet(Person $person) { echo "Hello, {$person->getName()}!\n"; } } class Person { public string $name; public function getName(): string { return $this->name; } }
Andaikan ada perpustakaan lain yang menyuap sesuatu dengan makanan:
class Feeder { public function feed(Eater $eater, string $food) { $eater->eat($food); } } class Animal { private $stomach = []; public function eat(string $food) { $stomach = $food; } }
Sekarang, katakan pengguna ingin menulis fungsi yang boleh makan dan bertanya khabar Pet
類。用戶不想僅僅為了 Pet
Tulis semula fungsi ini.
Bagaimana menulis Pet
以便同時使用 Greeter
和 Feeder
perpustakaan?
Mungkin ini kesnya?
class Pet extends Person, Animal { }
Malangnya, PHP tidak menyokong pelbagai warisan. Satu kelas hanya boleh mempunyai satu kelas. Kod di atas tidak sah. Jadi dalam keadaan semasa, pengguna hanya boleh menggunakan salah satu perpustakaan. 擴(kuò)展
. getName() 返回
$first_name
和 $last_name
代碼>)。您的庫類中可能沒有合理的默認(rèn)實現(xiàn) getName()
Bagaimana untuk menyelesaikan masalah ini menggunakan "antara muka" dalam PHP?
Menggunakan antara muka anda boleh menulis semula kedua-dua perpustakaan seperti ini:
Greeter
class Greeter { public function greet(Namer $namer) { echo "Hello, {$namer->getName()}!\n"; } } interface Namer { public function getName(): string; }
Feeder
class Feeder { public function feed(Eater $eater, string $food) { $eater->eat($food); } } interface Eater { public function eat(string $food); }
berikut sah sepenuhnya dalam PHP: Pet
class Pet implements Namer, Eater { private array $stomach = []; private string $name = ''; public function __construct(string $name) { $this->name = $name; } /** * Implements Namer. */ public function getName(): string { return $this->name; } /** * Implements Eater. */ public function eat(string $food) { $this->stomach[] = $food; } } $greeter = new Greeter(); $feeder = new Feeder(); $pet = new Pet('Paul'); $greeter->greet($pet); $feeder->feed($pet, 'a biscuit');Kini, objek kelas
ini boleh digunakan dengan perpustakaan Pet
類的對象可以與 Greeter
庫和 Feeder
dan perpustakaan
ArrayAccess
Agak seperti antara muka yang kami nyatakan sebelum ini, PHP menyediakan fungsi kepada kelas yang melaksanakannya. Tetapi bukannya menyediakan Greeter
或 Feeder
contoh di atas, teras PHP menyediakan sintaktik gula untuk kelas yang melaksanakan ArrayAccess. Ini bermakna anda boleh menggunakan kod yang lebih ringkas apabila berurusan dengan kelas yang melaksanakan antara muka AccessAccess.
Dalam contoh rasmi,
<?php class Obj implements ArrayAccess { private $container = array(); public function __construct() { $this->container = array( "one" => 1, "two" => 2, "three" => 3, ); } public function offsetSet($offset, $value) { if (is_null($offset)) { $this->container[] = $value; } else { $this->container[$offset] = $value; } } public function offsetExists($offset) { return isset($this->container[$offset]); } public function offsetUnset($offset) { unset($this->container[$offset]); } public function offsetGet($offset) { return isset($this->container[$offset]) ? $this->container[$offset] : null; } }
Jika anda melaksanakannya, gantikan dengan:
$obj = new Obj; $obj->offsetSet(10, "hello"); $obj->offsetSet(11, "world"); if ($obj->offsetUnset(12)) { $obj->offsetUnset(12); } echo $obj->offsetGet(11);
Anda boleh menggunakan $obj
dengan sintaks seperti tatasusunan untuk menjadikan kod anda lebih pendek:
$obj = new Obj; $obj[10] = "hello"; $obj[11] = "world"; if (isset($obj[12])) { unset($obj[12]); } echo $obj[11];