Интерфейсы не предназначены для повторного использования кода. Они предназначены для абстракции. Они позволяют классам, использующим шаблон, проверять интерфейс вместо базового класса шаблона. Таким образом он отделяет реализацию от декларации интерфейса.
Так что если ваш метод что-то делает с классом template
, проверка объекта экземпляра template
будет затруднять зависимость от этого класса. Но на самом деле вам все равно, какой класс вы получаете, вам просто все равно, если он придерживается интерфейса iTemplate
(так как это все, что вы звоните в любом случае).
public function foo(Template $template) {
против:
public function foo(iTemplate $template) {
Теперь, насколько код повторного использования, интерфейсы не предназначены для этого. Наследование обычно есть. В основном думать о наследовании как расширение абстракции. Позвольте мне привести вам пример:
Если бы вы создали набор классов для птиц, вы могли бы подойти к нему с наследованием и без него. Давайте посмотрим, как мы могли бы сделать это без:
interface iBird {
public function fly();
public function speak();
public function swim();
public function walk();
}
class Duck implements iBird {
public function fly() {
//Fly here
}
public function speak() {
// Quack here
}
public function swim() {
//Swim here
}
public function walk() {
//Walk here
}
}
class Turkey implements iBird {
public function fly() {
//Fly here, but limited
}
public function speak() {
//Make turkey sound here
}
public function swim() {
throw new Exception('Turkeys can not swim!');
}
public function walk() {
//Walk here
}
}
Теперь это простой пример, но вы можете видеть, что в этих двух птицах, то walk()
функция, вероятно, будет одинаковой (и, следовательно, нарушает DRY) ...
Давайте посмотрим, как это может выглядеть с Одноярусным наследования:
abstract class Bird implements iBird {
public function fly() {
//Fly here
}
abstract public function speak();
public function swim() {
//Swim here
}
public function walk() {
//Walk here
}
}
class Duck extends Bird {
public function speak() {
//Quack here
}
}
class Turkey extends Bird {
public function speak() {
//Make turkey sound here
}
public function swim() {
throw new Exception('Turkeys can not swim!');
}
}
Теперь вы можете видеть, мы просто повторно использовать 3 методы! Мы не объявляли speak()
, так как он всегда будет переоценен (так как ни одна из двух птиц не звучит одинаково).
Звучит хорошо? Ну, в зависимости от наших потребностей, мы можем захотеть добавить другие абстрактные типы. Так что давайте скажем, что у нас было много разных типов птиц ... У нас были бы некоторые, которые не плавали, поэтому мы могли бы создать абстрактный класс NonSwimmingBird
, который расширяет Bird
, но выдает нам исключение. Или a NonFlyingBird
, или a ShortRangeBird
...
Теперь мы действительно находимся на пути к повторному использованию кода, но мы ударяем о стену в другую область. Предположим, у нас есть птица, которая не летает и не плавает. Какой класс мы наследуем? В любом случае, мы дублируем код. Поэтому нам нужно найти другой выход. Ну, как мы это сделаем? Через Design Patterns ... Вместо прямого наследования мы могли бы использовать узор декоратора, чтобы добавить эти черты «на лету». (Существуют и другие шаблоны, которые можно использовать здесь, и нужно показать, что наследование само по себе не устраивает всех потребностей. И шаблоны сами по себе тоже не будут. Вам нужна хорошая архитектура, использующая оба мира на основе ваших точных потребностей) ...
Дело в том, что все зависит от ваших потребностей. Если у вас есть только 2 «класса» объектов, которые вы собираетесь архитектовать гораздо проще, чем если бы вы планировали иметь тысячи. Пункт того, что я написал здесь, состоит в том, чтобы продемонстрировать, как вы можете использовать прямое наследование для принудительного исполнения некоторых СУХИХ принципов (но также и то, как прямое наследование может вызвать дублирование кода). Главное, не пытайтесь придерживаться DRY только потому, что вы не хотите повторять себя. Придерживайтесь DRY, но убедитесь, что вы объединяетесь и расширяетесь там, где это разумно, иначе вы создаете себе головную боль обслуживания. Придерживайтесь Single Responsibility Principal, и вы должны быть в порядке ...
может указать, где вы нашли этот код? Я нахожусь на этапе обучения, и я стараюсь учиться на примерах. – dole