Является ли бинарный узел наследником интерфейса небинарного узла? Написал базовый интерфейс узла.interface NodeInterface { public function key(); public function value(); public function __construct($key, $value); public function contains(NodeInterface $node): bool; public function addChild(NodeInterface $node); public function setParent(NodeInterface $node); public function parent(): ?NodeInterface; public function children(): array; // ... } Реализовывая класс Node на основе него, мы получаем типичный узел с множеством детей. Ок. Но вот, допустим, нужно написать класс бинарного узла для бинарного дерева. Подузлов может быть только 2: left, right. Как реализовать?Наследоваться от Node и задавать жесткие ограничения:interface BinaryNodeInterface extends NodeInterface { public function left(): ?BinaryNodeInterface; public function right(): ?BinaryNodeInterface; } class BinaryNode extends Node implements BinaryNodeInterface { public function left(): ?BinaryNodeInterface { return $this->children[0] ?? null; } public function right(): ?BinaryNodeInterface { return $this->children[1] ?? null; } public function addChild(NodeInterface $node) { if (count($this->children) < 2) { parent::addChild($node); } } } Но тогда грубо нарушается принцип подстановки из SOLID. Сделать два разных базовых интерфейса типа MultiNodeInterface и BinaryNodeInterface, но тогда получится дублирование кода и не универсально.
Лучшим решением в данном случае будет создание отдельного интерфейса BinaryNodeInterface, содержащего только методы, специфичные для бинарного узла, и имплементация его в классе BinaryNode. Таким образом, у нас будет отдельный интерфейс для бинарного узла, который не будет наследоваться от NodeInterface, и при этом не будет нарушаться принцип подстановки из SOLID.
Примерно такая структура может выглядеть следующим образом:
interface NodeInterface { public function key(); public function value(); public function __construct($key, $value); public function contains(NodeInterface $node): bool; public function addChild(NodeInterface $node); public function setParent(NodeInterface $node); public function parent(): ?NodeInterface; public function children(): array; // ... } interface BinaryNodeInterface { public function left(): ?BinaryNodeInterface; public function right(): ?BinaryNodeInterface; } class Node implements NodeInterface { // реализация методов интерфейса NodeInterface } class BinaryNode extends Node implements BinaryNodeInterface { public function left(): ?BinaryNodeInterface { return $this->children[0] ?? null; } public function right(): ?BinaryNodeInterface { return $this->children[1] ?? null; } public function addChild(NodeInterface $node) { if (count($this->children) < 2) { parent::addChild($node); } } }
Таким образом, мы реализуем специфичные методы для бинарного узла в интерфейсе BinaryNodeInterface и в классе BinaryNode, не затрагивая базовый интерфейс NodeInterface и при этом соблюдая принципы SOLID.
Лучшим решением в данном случае будет создание отдельного интерфейса BinaryNodeInterface, содержащего только методы, специфичные для бинарного узла, и имплементация его в классе BinaryNode. Таким образом, у нас будет отдельный интерфейс для бинарного узла, который не будет наследоваться от NodeInterface, и при этом не будет нарушаться принцип подстановки из SOLID.
Примерно такая структура может выглядеть следующим образом:
interface NodeInterface{
public function key();
public function value();
public function __construct($key, $value);
public function contains(NodeInterface $node): bool;
public function addChild(NodeInterface $node);
public function setParent(NodeInterface $node);
public function parent(): ?NodeInterface;
public function children(): array;
// ...
}
interface BinaryNodeInterface
{
public function left(): ?BinaryNodeInterface;
public function right(): ?BinaryNodeInterface;
}
class Node implements NodeInterface
{
// реализация методов интерфейса NodeInterface
}
class BinaryNode extends Node implements BinaryNodeInterface
{
public function left(): ?BinaryNodeInterface
{
return $this->children[0] ?? null;
}
public function right(): ?BinaryNodeInterface
{
return $this->children[1] ?? null;
}
public function addChild(NodeInterface $node)
{
if (count($this->children) < 2) {
parent::addChild($node);
}
}
}
Таким образом, мы реализуем специфичные методы для бинарного узла в интерфейсе BinaryNodeInterface и в классе BinaryNode, не затрагивая базовый интерфейс NodeInterface и при этом соблюдая принципы SOLID.