Динамически реализовать интерфейс на основе значения свойства объекта в PHP? - PullRequest
0 голосов
/ 11 сентября 2018

Допустим, у нас есть класс 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 голосов
/ 11 сентября 2018

Как я уже говорил, невозможно реализовать это с помощью PHP.

Но вы могли бы реализовать что-то, используя, например, декораторы.

Глупый декоратор подход:

У вас будет свой класс для украшения:

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;

    }
}

Ваши интерфейсы, Trainable и Huggable:

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, который реализует 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;
    }
}

Наконец, вы будете использовать еготаким образом:

$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
)
 */

Отношения «многие ко многим» между «Собаками» и «Категориями» я оставляю на ваше усмотрение.Это отдельная проблема, и ее можно решить разными способами.

...