国产av日韩一区二区三区精品,成人性爱视频在线观看,国产,欧美,日韩,一区,www.成色av久久成人,2222eeee成人天堂

PHP 接口實(shí)際上如何改變類(lèi)的行為
P粉289775043
P粉289775043 2023-09-02 23:49:28
0
1
711
<p>根據(jù) PHP 文檔,</p> <blockquote> <p>對(duì)象接口允許您創(chuàng)建指定類(lèi)必須實(shí)現(xiàn)哪些方法的代碼,而無(wú)需定義這些方法的實(shí)現(xiàn)方式。</p> </blockquote> <p>因此,接口就像一個(gè)具有預(yù)定義方法的類(lèi),仍然需要使用 <code>-></code> 符號(hào)來(lái)訪問(wèn)</p> <p>但是,ArrayAccess 接口提供對(duì)對(duì)象作為數(shù)組的訪問(wèn)??梢允褂?<code>$object->property</code> 和 <code>$object["property"]</code></p> 訪問(wèn)對(duì)象 <p>我無(wú)法理解 ArrayAccess 如何使更改對(duì)象語(yǔ)法成為可能。我編寫(xiě)了一段代碼來(lái)嘗試復(fù)制 <code>ArrayAccess</code> 方法<em>僅一個(gè)</em>的效果,但它拋出錯(cuò)誤</p> <pre class="brush:php;toolbar:false;">// Using the PHP ArrayAccess Interface namespace A { class myclass implements \ArrayAccess { public function offsetExists($offset) { return true; } public function offsetGet($offset) { // changed behaviour return $this->{$offset} ?? null; } public function offsetSet($offset, $value) {} public function offsetUnset($offset) {} } $myclass = new myclass(); $myclass->access = 'Interface'; echo $myclass['access']; // "Interface" }; //Trying to implement my own ArrayAccess Interface namespace B { interface MyArrayAccess { public function offsetGet($offset); } class myclass implements MyArrayAccess { public function offsetGet($offset) { // change behaviour return $this->{$offset} ?? null; } } $myclass = new myclass(); $myclass->access = 'Interface'; echo $myclass['access']; // Fatal error: Uncaught Error: Cannot use object of type B\myclass as array } </pre> <p>請(qǐng)幫我正確解釋一下。謝謝</p>
P粉289775043
P粉289775043

全部回復(fù)(1)
P粉702946921

我并不是說(shuō)接口“改變了類(lèi)的行為”,而是說(shuō)接口使擴(kuò)展類(lèi)功能變得容易。

要理解接口,作為一個(gè)面向?qū)ο蟮木幊谈拍?,我們首先?yīng)該理解它要解決什么問(wèn)題。

“Interface”旨在解決什么問(wèn)題?

接口是一種契約。這是在 PHP 中實(shí)現(xiàn) duck-typing 的方法。您需要從庫(kù)編寫(xiě)者的角度思考,他希望向其他人公開(kāi)功能。例如,

class Greeter
{
    public function greet($person)
    {
        echo "Hello, {$person->getName()}!\n";
    }
}

為了確保庫(kù)用戶知道 $person 需要有 getName() 方法,您可以創(chuàng)建一個(gè)類(lèi) Person > 有一個(gè) getName() 方法。然后使用 類(lèi)型聲明 來(lái)檢測(cè)代碼執(zhí)行時(shí)的潛在錯(cuò)誤已解析。

class Greeter
{
    public function greet(Person $person)
    {
        echo "Hello, {$person->getName()}!\n";
    }
}

class Person
{
    public string $name;
    public function getName(): string
    {
        return $this->name;
    }
}

假設(shè)有另一個(gè)庫(kù)可以用食物來(lái)喂養(yǎng)東西:

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

class Animal {
    private $stomach = [];
    public function eat(string $food) {
        $stomach = $food;
    }
}

考慮這個(gè)...

現(xiàn)在,假設(shè)用戶想要編寫(xiě)一個(gè)既可以吃飯又可以打招呼的 Pet 類(lèi)。用戶不想僅僅為了 Pet 再次編寫(xiě)這些功能。

如何編寫(xiě) Pet 以便同時(shí)使用 GreeterFeeder 庫(kù)?

也許是這樣的?

class Pet extends Person, Animal {
}

不幸的是,PHP 不支持多重繼承。一個(gè)類(lèi)只能擴(kuò)展一個(gè)類(lèi)。上面的代碼無(wú)效。所以在目前的情況下,用戶只能使用其中一個(gè)庫(kù)。

此外,對(duì)于不同的事物,“名稱(chēng)”可能是一個(gè)非常不同的概念(例如,一個(gè)人可能會(huì)使用 getName() 返回 $first_name$last_name 代碼>)。您的庫(kù)類(lèi)中可能沒(méi)有合理的默認(rèn)實(shí)現(xiàn) getName() 方法。

所以,作為一名庫(kù)編寫(xiě)者,您希望他/她的庫(kù)對(duì)用戶盡可能靈活。你能做什么?

如何用 PHP 中的“接口”解決這個(gè)問(wèn)題?

接口是方法簽名的聲明。這是在沒(méi)有具體類(lèi)/繼承要求的情況下聲明庫(kù)要求的快捷方式。

使用接口,您可以像這樣重寫(xiě)兩個(gè)庫(kù):

Greeter 庫(kù)

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

interface Namer {
    public function getName(): string;
}

Feeder 庫(kù)

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

interface Eater {
    public function eat(string $food);
}

不需要一個(gè)具體的類(lèi)(或父類(lèi)繼承),一個(gè)類(lèi)可以實(shí)現(xiàn)多個(gè)接口。所以下面的 Pet 類(lèi)在 PHP 中是完全有效的:

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');

現(xiàn)在,此 Pet 類(lèi)的對(duì)象可以與 Greeter 庫(kù)和 Feeder 庫(kù)一起使用。

ArrayAccess 接口怎么樣?

ArrayAccess 接口不是由第三方聲明的接口庫(kù)編寫(xiě)者,但由核心 PHP 編寫(xiě)者編寫(xiě)。核心PHP編寫(xiě)器對(duì)此提供了更深刻的支持。

有點(diǎn)像我們之前提到的接口,PHP 為實(shí)現(xiàn)它的類(lèi)提供功能。但核心 PHP 不是提供上面的 GreeterFeeder 示例,而是提供 實(shí)現(xiàn) ArrayAccess 的類(lèi)的語(yǔ)法糖。這意味著您可以使用更簡(jiǎn)潔的代碼來(lái)處理實(shí)現(xiàn) AccessAccess 接口的類(lèi)。

在官方示例中,

<?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;
    }
}

如果您實(shí)現(xiàn)了它們,則代替這些:

$obj = new Obj;
$obj->offsetSet(10, "hello");
$obj->offsetSet(11, "world");
if ($obj->offsetUnset(12)) {
    $obj->offsetUnset(12);
}
echo $obj->offsetGet(11);

您可以將 $obj 與類(lèi)似數(shù)組的語(yǔ)法一起使用,以使代碼更短:

$obj = new Obj;

$obj[10] = "hello";
$obj[11] = "world";
if (isset($obj[12])) {
    unset($obj[12]);
}
echo $obj[11];
最新下載
更多>
網(wǎng)站特效
網(wǎng)站源碼
網(wǎng)站素材
前端模板