В PHP 5.5, если я укажу иерархию интерфейсов и параллельную иерархию классов, я получу дочерние классы, которые наследуют определенный тип через более чем одно отношение. Это говорит о плохом дизайне? Может ли это создать проблемы?
Например, посмотрите код:
interface foo {}
interface bar extends foo {}
class myFoo implements foo {}
class myBar extends myFoo implements bar {}
В этом примере myBar наследует тип ‘foo’ через два отношения:
Причина, по которой у меня есть отношения 1: 1 между интерфейсами и классами, заключается в том, что я могу заменять прокси и макеты для конкретных классов на уровне детализации. (Все параметры моего метода выражены в терминах интерфейсов).
Я мог бы прекратить использование наследования в моих интерфейсах, но это, кажется, идет вразрез с полиморфизмом. Кроме того, это создает проблемы, когда я использую свои интерфейсы для определения сигнатур методов (т. Е. Не только для установления общего типа).
Это не имеет значения в любом случае. Подумайте об этом с точки зрения «потребителя» интерфейса, а не с абстрактной идеи самого интерфейса:
function (bar $bar) {
...
}
Это где резина встречает дорогу с интерфейсами. Все, что интересует эта функция — это объект, который имеет методы, которые соответствуют методам, определенным в bar
интерфейс. Неважно, как именно этот объект реализует эти методы, просто он имеет все методы, которые interface bar
определяет. Также не имеет значения, какие методы наследуются, в интерфейсе или в объекте. Суммарная совокупность созданного объекта — это все, что имеет значение.
Сказав это, вы можете подумать о вашем интерфейсе и дизайне класса, тем не менее. То, что вы делаете, само по себе не так, но есть может быть лучшим способом приблизиться к интерфейсам. Не думайте об интерфейсах как об эскизе для класса, думайте об интерфейсах как об определении способности. Для этого, опять же, думать с точки зрения потребитель такого интерфейса. Например:
function renderThumbnail(Imaginable $item) {
printf('<img src="%s">', $item->getHighestResolutionImage()->getUrl());
}interface Imaginable {
/**
* @return Image[]
*/
public function getImages();
/**
* @return Image
*/
public function getHighestResolutionImage();
}
Это демонстрирует один конкретный возможность объект может иметь. любой объект может иметь связанные изображения. Любой класс, реализующий Imaginable
Интерфейс просто заявляет, что может предоставить изображение по запросу. renderThumbnail
Функция просто нуждается в любом объекте, который имеет изображение. Неважно, какой объект передается в него, этот объект может также реализовывать тысячу других интерфейсов и иметь класс любого типа, важная часть заключается в том, что он может выполнять эту конкретную вещь.
Если вы думаете об этом с точки зрения «-able
«Возможности интерфейсов, должно быть очевидно, что вы, вероятно, не получите две иерархии, работающие параллельно, и это, вероятно, будет лучшим дизайном.
Других решений пока нет …