【问题标题】:Dynamically implement interface based on object property value in PHP?PHP中基于对象属性值动态实现接口?
【发布时间】:2019-02-16 03:54:06
【问题描述】:

假设我们有一个 Dog 类和一个 Category 类,狗可以被分配到。

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

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

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

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

我可以想象“pet dog”和“shepherd dog”有不同的界面,例如

interface Huggable {
    function hug();
}

interface Trainable {
    function train();
}

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

有可能吗?

【问题讨论】:

  • PHP 不允许您动态混合类。这可能对traits 很有用

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


【解决方案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;
}

一个实现可训练的装饰器,并将特定类别添加到装饰实例:

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

另一个实现HuggableFluffyDecorator

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

最后,你会这样使用它:

$fido    = new Animal();
$fidoPet = new PetDecorator($fido);

$fidoPet->train();
// I'm housebroken!

print_r($fidoPet->getCategories());
/*
Array
(
    [0] => pet
)
*/

$fidoLove = new FluffyDecorator($fidoPet);
// Much hug!
$fidoLove->hug();

print_r($fidoLove->getCategories());
/*
 Array
(
    [0] => pet
    [1] => loveBear
)
 */

“Dogs”和“Categories”之间的多对多关系由您决定。这是一个单独的问题,可以通过多种不同的方式处理。

【讨论】:

  • 谢谢!我最近刚接触 oop,我了解 oop 的强大功能和简洁性。这篇文章帮助我了解了扩展的工作原理。干得好,先生!
猜你喜欢
  • 1970-01-01
  • 2023-03-29
  • 2018-07-13
  • 1970-01-01
  • 2020-08-21
  • 2011-04-17
  • 2011-10-26
  • 2011-03-30
  • 2012-07-22
相关资源
最近更新 更多