Следует ли разрешать типу наследоваться как интерфейсами, так и классами?

В PHP 5.5, если я укажу иерархию интерфейсов и параллельную иерархию классов, я получу дочерние классы, которые наследуют определенный тип через более чем одно отношение. Это говорит о плохом дизайне? Может ли это создать проблемы?

Например, посмотрите код:

interface foo {}
interface bar extends foo {}

class myFoo implements foo {}
class myBar extends myFoo implements bar {}

В этом примере myBar наследует тип ‘foo’ через два отношения:

  • Он наследует ‘foo’ от своего конкретного родителя (myFoo)
  • Он наследует ‘foo’ от интерфейса, который он реализует (bar)

Причина, по которой у меня есть отношения 1: 1 между интерфейсами и классами, заключается в том, что я могу заменять прокси и макеты для конкретных классов на уровне детализации. (Все параметры моего метода выражены в терминах интерфейсов).

Я мог бы прекратить использование наследования в моих интерфейсах, но это, кажется, идет вразрез с полиморфизмом. Кроме того, это создает проблемы, когда я использую свои интерфейсы для определения сигнатур методов (т. Е. Не только для установления общего типа).

0

Решение

Это не имеет значения в любом случае. Подумайте об этом с точки зрения «потребителя» интерфейса, а не с абстрактной идеи самого интерфейса:

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«Возможности интерфейсов, должно быть очевидно, что вы, вероятно, не получите две иерархии, работающие параллельно, и это, вероятно, будет лучшим дизайном.

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]