alexeyyashin/ducktyping

PHP 的简单鸭子类型实现

v1.0.1 2020-12-02 12:42 UTC

This package is auto-updated.

Last update: 2024-09-29 05:29:15 UTC


README

ducktyping 是一个简单的基于反射的 PHP 鸭子类型实现

如果它像鸭子走路,它像鸭子嘎嘎叫,那么它一定是只鸭子

安装

使用 Composer

composer require alexeyyashin/ducktyping

不使用 Composer

  • 将仓库文件复制到您需要的地方
  • 包含 autoload.php
include_once 'ducktyping-master/autoload.php';

基本用法

检查方法实现

duck_check(Duck::class)->implementing(Bird::class);

如果类 Duck 实现了类 Bird 中存在的所有方法(考虑到 "静态" 修饰符),则返回 true

注意,您可以在 duck_check 函数和 implementing 方法中同时使用类名(作为 string)或 object

$duck = new Duck;
$bird = new Bird;

duck_check($duck)->implementing($bird);

检查单个方法的存在性

duck_check(Duck::class)->hasMethod('fly', $check_static)

解释

让我们从一个基本独立类开始

class Animal
{   
    public function run() {}
}

class Plant
{
    public function growLeaves() {}
}

然后添加一些子类

class Bird extends Animal
{
    public function fly() {}
}

很明显

var_dump(new Bird instanceof Animal); // bool(true)

但是如果我们添加一些独立类

class Duck
{
    public function run() {}
    
    public function fly() {}
    
    public function quackle() {}
}

我们会得到

var_dump(new Duck instanceof Bird); // bool(false)

尽管它既会 "跑" 也会 "飞",但这只是因为类 Duck 没有继承类 Bird

要检查这一点,我们可以通过 duck typing 来查看类 Duck 是否拥有类 Bird 中的所有方法

var_dump(duck_check(Duck::class)->implementing(Bird::class)); // bool(true)

// BUT, Duck does not have "growLeaves" method, so

var_dump(duck_check(Duck::class)->implementing(Plant::class)) // bool(false)

多重类实现附加功能

class Bulbasaur extends Pokemon
{
    public static $link = "https://en.wikipedia.org/wiki/Bulbasaur";
    
    public function run() {}
    
    public function growLeaves() {}
    
    public function fight() {}
}

$check = duck_check(new Bulbasaur);

$check->implementing(Pokemon::class) // true - because of inheritance
$check->implementing(Animal::class) // true - because of "run" method
$check->implementing(Plant::class) // true - because of "growLeaves" method
$check->implementing(Bird::class) // false - because of "fly" method absence

进一步

我想知道我们是否也应该检查测试类/对象中的公共属性。所以我需要取消注释那一行或删除它。

也许可以添加方法签名检查。