在PHP中基于对象属性值动态实现接口?

时间:2018-09-11 15:26:02

标签: php oop architecture object-oriented-analysis system-design

假设我们有一个Dog类和一个Category类,可以将狗分配给它们。

class Dog {
    function categories() {} // Return the categories of the dog.
}

class Category {
    function dogs() {} // Return the dogs under this category.
}

狗可以具有“宠物”和“牧羊人”类别。分配给“宠物”类别时,它是“宠物狗”,“牧羊人”也是如此。

宠物狗和牧羊犬具有不同的属性和功能。但是,狗既可以是“宠物狗”又可以是“牧羊犬”。

我可以想象,例如“宠物狗”和“牧羊犬”具有不同的界面

interface Huggable {
    function hug()
}

interface Trainable {
    function train()
}

理想情况下,当狗被分配到“宠物”类别时,它会实现Huggable接口;如果狗被分配到“牧羊人”类别,则它会实现Trainable类别。

有可能吗?

1 个答案:

答案 0 :(得分:1)

正如我评论的那样,不可能用PHP本机实现。

例如,您可以使用装饰器来实现某些东西。

一种愚蠢的decorator方法:

您将有待装饰的课程:

class Animal {

    protected $categories = [];

    public function getCategories() {
        return $this->categories;
    }

    public function addCategory( string $category ) {
        // we should check the animal doesn't already belong to this category
        $this->categories[] = $category;

    }
}

您的界面TrainableHuggable

interface Trainable {

    function train();
}

interface Huggable {
    // see https://github.com/php-fig/fig-standards/blob/master/proposed/psr-8-hug/psr-8-hug.md
    function hug() : bool;
}

一个实现了Trainable的装饰器,并将特定的类别添加到装饰的实例中:

class PetDecorator extends Animal implements Trainable {


    public function __construct( Animal $animal ) {

        $this->categories = $animal->getCategories();
        $this->addCategory('pet');

    }

    public function train() {
        echo "I'm housebroken!\n";
    }
}

另外一个实现FluffyDecorator的{​​{1}}

Huggable

最后,您将这样使用它:

class FluffyDecorator extends Animal implements Huggable {

    public function __construct( Animal $animal ) {

        $this->categories = $animal->getCategories();
        $this->addCategory('loveBear');
    }

    public function hug( ) :bool {
        echo "Much hug!\n";
        return true;
    }
}

“狗”和“类别”之间的多对多关系由您自己决定。那是一个单独的问题,可以通过许多不同的方式来处理。