男女疯狂一边摸一边做羞羞视频|啊好深好硬快点用力别停动态图|亚洲一区无码中文字幕|特级无码毛片免费视频播放▽|久久狠狠躁免费观看|国内精品久久久久久网站

協(xié)變與逆變

在 PHP 7.2.0 里,通過(guò)對子類(lèi)方法里參數的類(lèi)型放寬限制,實(shí)現對逆變的部分支持。 自 PHP 7.4.0 起開(kāi)始支持完整的協(xié)變和逆變。

協(xié)變使子類(lèi)比父類(lèi)方法能返回更具體的類(lèi)型; 逆變使子類(lèi)比父類(lèi)方法參數類(lèi)型能接受更模糊的類(lèi)型。

在以下情況下,類(lèi)型聲明被認為更具體:

如果情況相反,則類(lèi)型類(lèi)被認為是模糊的。

協(xié)變

創(chuàng )建一個(gè)名為 Animal 的簡(jiǎn)單的抽象父類(lèi),用于演示什么是協(xié)變。 兩個(gè)子類(lèi):CatDog 擴展(extended)了 Animal。

<?php

abstract class Animal
{
    protected 
string $name;

    public function 
__construct(string $name)
    {
        
$this->name $name;
    }

    abstract public function 
speak();
}

class 
Dog extends Animal
{
    public function 
speak()
    {
        echo 
$this->name " barks";
    }
}

class 
Cat extends Animal 
{
    public function 
speak()
    {
        echo 
$this->name " meows";
    }
}

注意:在這個(gè)例子中,沒(méi)有方法返回了值。 將通過(guò)添加個(gè)別工廠(chǎng)方法,創(chuàng )建并返回 Animal、Cat、Dog 類(lèi)型的新對象。

<?php

interface AnimalShelter
{
    public function 
adopt(string $name): Animal;
}

class 
CatShelter implements AnimalShelter
{
    public function 
adopt(string $name): Cat // 返回類(lèi)的類(lèi)型不僅限于 Animal,還可以是 Cat 類(lèi)型
    
{
        return new 
Cat($name);
    }
}

class 
DogShelter implements AnimalShelter
{
    public function 
adopt(string $name): Dog // 返回類(lèi)的類(lèi)型不僅限于 Animal,還可以是 Dog 類(lèi)型
    
{
        return new 
Dog($name);
    }
}

$kitty = (new CatShelter)->adopt("Ricky");
$kitty->speak();
echo 
"\n";

$doggy = (new DogShelter)->adopt("Mavrick");
$doggy->speak();

以上例程會(huì )輸出:

Ricky meows
Mavrick barks

逆變

繼續上一個(gè)例子,除了 Animal、 Cat、Dog,我們還添加了 Food、AnimalFood 類(lèi), 同時(shí)為抽象類(lèi) Animal 添加了一個(gè) eat(AnimalFood $food) 方法。

<?php

class Food {}

class 
AnimalFood extends Food {}

abstract class 
Animal
{
    protected 
string $name;

    public function 
__construct(string $name)
    {
        
$this->name $name;
    }

    public function 
eat(AnimalFood $food)
    {
        echo 
$this->name " eats " get_class($food);
    }
}

為了演示什么是逆變,Dog 類(lèi)重寫(xiě)(overridden)了 eat 方法, 允許傳入任意 Food 類(lèi)型的對象。 而 Cat 類(lèi)保持不變。

<?php

class Dog extends Animal
{
    public function 
eat(Food $food) {
        echo 
$this->name " eats " get_class($food);
    }
}

下面的例子展示了逆變。

<?php

$kitty 
= (new CatShelter)->adopt("Ricky");
$catFood = new AnimalFood();
$kitty->eat($catFood);
echo 
"\n";

$doggy = (new DogShelter)->adopt("Mavrick");
$banana = new Food();
$doggy->eat($banana);

以上例程會(huì )輸出:

Ricky eats AnimalFood
Mavrick eats Food

$kitty 若嘗試 eat $banana 會(huì )發(fā)生什么呢?

$kitty->eat($banana);

以上例程會(huì )輸出:

Fatal error: Uncaught TypeError: Argument 1 passed to Animal::eat() must be an instance of AnimalFood, instance of Food given
男女疯狂一边摸一边做羞羞视频|啊好深好硬快点用力别停动态图|亚洲一区无码中文字幕|特级无码毛片免费视频播放▽|久久狠狠躁免费观看|国内精品久久久久久网站