cari

Rumah  >  Soal Jawab  >  teks badan

Bagaimana antara muka PHP sebenarnya mengubah tingkah laku kelas

<p>Menurut dokumentasi PHP, </p> <blockquote> <p>Antara muka objek membolehkan anda mencipta kod yang menentukan kaedah yang mesti dilaksanakan oleh kelas tanpa menentukan cara kaedah tersebut dilaksanakan. </p> </blockquote> <p>Oleh itu, antara muka adalah seperti kelas dengan kaedah pratakrif yang masih perlu diakses menggunakan <kod>-></code> <p>Walau bagaimanapun, antara muka ArrayAccess menyediakan akses kepada objek sebagai tatasusunan. Objek boleh diakses menggunakan <kod>$object->property</code> dan <code>$object["property"]</code></p> <p>Saya tidak dapat memahami bagaimana ArrayAccess memungkinkan untuk menukar sintaks objek. Saya menulis sekeping kod untuk cuba meniru kesan kaedah <kod>ArrayAccess</code>hanya satu</em>, tetapi ia menimbulkan ralat</p> <pre class="brush:php;toolbar:false;">// Menggunakan Antara Muka PHP ArrayAccess ruang nama A { kelas myclass melaksanakan ArrayAccess { public function offsetExists($offset) { return true } fungsi awam offsetGet($offset) { // berubah tingkah laku kembalikan $this->{$offset} ?? } fungsi awam offsetSet($offset, $value) {} fungsi awam offsetUnset($offset) {} } $myclass = new myclass(); $myclass->access = 'Antaramuka'; echo $myclass['access']; // "Antaramuka" }; //Cuba untuk melaksanakan Antara Muka ArrayAccess saya sendiri ruang nama B { antara muka MyArrayAccess { fungsi awam offsetGet($offset); } kelas myclass melaksanakan MyArrayAccess { fungsi awam offsetGet($offset) { // ubah tingkah laku kembalikan $this->{$offset} ?? } } $myclass = new myclass(); $myclass->access = 'Antaramuka'; echo $myclass['access']; // Ralat maut: Ralat Tidak Ditangkap: Tidak boleh menggunakan objek jenis Bmyclass sebagai tatasusunan } </pra> <p>Tolong bantu saya menerangkannya dengan betul. Terima kasih</p>
P粉289775043P粉289775043458 hari yang lalu609

membalas semua(1)saya akan balas

  • P粉702946921

    P粉7029469212023-09-03 20:17:24

    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.

    Apakah masalah yang ingin diselesaikan oleh "Antara Muka"?

    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() 方法,您可以创建一个类 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;
        }
    }
    
    

    Pertimbangkan ini...

    Sekarang, katakan pengguna ingin menulis fungsi yang boleh makan dan bertanya khabar Pet 类。用户不想仅仅为了 Pet Tulis semula fungsi ini.

    Bagaimana menulis Pet 以便同时使用 GreeterFeeder 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. 扩展

    Selain itu, "nama" boleh menjadi konsep yang sangat berbeza untuk perkara yang berbeza (mis. seseorang mungkin menggunakan kaedah

    . getName() 返回 $first_name$last_name )。您的库类中可能没有合理的默认实现 getName()

    Jadi, sebagai penulis perpustakaan, anda mahu perpustakaannya sefleksibel mungkin untuk pengguna. apa yang kau boleh buat?

    Bagaimana untuk menyelesaikan masalah ini menggunakan "antara muka" dalam PHP?

    Antara muka ialah pengisytiharan tandatangan kaedah. Ini ialah cara cepat untuk mengisytiharkan keperluan perpustakaan tanpa keperluan kelas/warisan konkrit.

    Menggunakan antara muka anda boleh menulis semula kedua-dua perpustakaan seperti ini:

    perpustakaanGreeter
    class Greeter {
        public function greet(Namer $namer) {
            echo "Hello, {$namer->getName()}!\n";
        }
    }
    
    interface Namer {
        public function getName(): string;
    }
    

    perpustakaanFeeder
    class Feeder {
        public function feed(Eater $eater, string $food) {
            $eater->eat($food);
        }
    }
    
    interface Eater {
        public function eat(string $food);
    }
    
    

    Tidak memerlukan kelas tertentu (atau warisan kelas induk), kelas boleh melaksanakan berbilang antara muka. Jadi kelas

    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

    Bagaimana pula dengan antara muka?

    Antara muka ArrayAccess

    tidak diisytiharkan oleh penulis perpustakaan antara muka pihak ketiga, tetapi ditulis oleh penulis teras PHP. Penulis PHP teras menyediakan sokongan yang lebih mendalam untuk ini. 🎜

    Agak seperti antara muka yang kami nyatakan sebelum ini, PHP menyediakan fungsi kepada kelas yang melaksanakannya. Tetapi bukannya menyediakan GreeterFeeder 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];
    

    balas
    0
  • Batalbalas