Написал базовый интерфейс узла.
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, но тогда получится дублирование кода и не универсально.