2010-09-13 2 views
3

Я изучил в php oop и укомплектован концепцией многоразового кода.PHP: как повторно использовать код (oop)?

Я видел пример как

interface iTemplate 
{ 
    public function setVariable($name, $var); 
    public function getHtml($template); 
} 
And implement it: 

// Implement the interface 
class Template implements iTemplate 
{ 
    private $vars = array(); 

    public function setVariable($name, $var) 
    { 
     $this->vars[$name] = $var; 
    } 

    public function getHtml($template) 
    { 
     foreach($this->vars as $name => $value) { 
      $template = str_replace('{' . $name . '}', $value, $template); 
     } 

     return $template; 
    } 
} 

Я могу понять код, но не знаю, почему он является многоразовым. Каждый раз, когда я хочу добавить новую функцию в интерфейс iTemplate, мне также необходимо изменить класс Template. Я не понимаю понятия «повторное использование». Я ценю любую помощь. Благодарю.

+0

может указать, где вы нашли этот код? Я нахожусь на этапе обучения, и я стараюсь учиться на примерах. – dole

ответ

6

Интерфейсы не предназначены для повторного использования кода. Они предназначены для абстракции. Они позволяют классам, использующим шаблон, проверять интерфейс вместо базового класса шаблона. Таким образом он отделяет реализацию от декларации интерфейса.

Так что если ваш метод что-то делает с классом 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, и вы должны быть в порядке ...

+0

очень очень хорошее объяснение .... спасибо миллион. – FatDeveloper

0

Интерфейс пишет только 1 раз в начале разработки. И только после этого пишет другие классы, реализующие этот интерфейс. Интерфейс - это основа. Примечание: метод setVariable не требуется. В PHP есть хорошие магические методы: __get() и __set().

+0

Спасибо. но предположим, что мы создаем еще один класс под названием Product tool iTemplate. Я все еще должен набирать метод setVariable и getHtml в своем классе с интерфейсом или без него, так что в чем смысл? – FatDeveloper

0

Интерфейсы обычно полезны в тех случаях, когда вы хотите, чтобы что-то было взаимозаменяемым. Представьте, что вы создали приложение, поддерживающее плагин. Затем у вас есть интерфейс iPlugin:

interface iPlugin { 
    public function init(); 
    /* .. */ 
} 

и все плагины будут реализовывать этот интерфейс. Менеджер плагинов тогда мог бы легко проверить, реализует ли плагин интерфейс и вызывает на нем метод init().

0

Код не обязательно должен быть OO для повторного использования, хотя во многих случаях это помогает.

Код, конечно, не обязательно должен использовать интерфейсы для повторного использования, хотя в некоторых случаях это также поможет.

Ключ к написанию многоразового кода заключается в написании кода, который четко написан, хорошо прокомментирован, использует согласованные соглашения об именах и вызовах и является более общим, чем это должно быть строго для данной проблемы.

Один из простейших и наиболее эффективных методов написания многоразового кода в PHP - это метод, который принимает либо переменное количество аргументов, либо принимает ассоциативный массив параметров.

Часто код, который не начинал использовать «намереваясь» для повторного использования, оказывается тем, что вы захотите повторно использовать. Как правило, код запускается «inline», а затем вы обнаруживаете, что вам нужно делать точно или почти точно одно и то же в нескольких местах. Когда вы копируете и вставляете код, пришло время реорганизовать его как функцию.

Аналогичным образом, если вы захотите, чтобы функция, которую вы определили в файле X, была бы действительно полезной в файле Y, пришло время переместить ее в модуль.

Лучший способ узнать все это по опыту. Некоторые люди расскажут вам о том, чтобы с самого начала архитектовать этот материал, и это, безусловно, хорошая идея, если у вас есть понимание и опыт, чтобы сделать это, но это так же справедливо для этого снизу вверх, и это, вероятно, лучший способ учить.

0

Повторное использование объектно-ориентированного программирования - это использование предыдущего класса или функции или метода в данном классе, но без проблем предыдущего класса.

Смежные вопросы