2013-12-06 3 views
10

При определении структуры и наследования интерфейса и/или абстрактного класса, какой из них является лучшей практикой? И почему? Вот 2 примера:PHP-интерфейс и абстрактная классная передовая практика для наследования?

Вот пример [Interface] -> [Abstract Class] -> [Class]

Interface DataInterface 
{ 
    public function __construct($connection); 
    public function connected(); 
    public function get(); 
} 

Abstract class BaseData implements DataInterface 
{ 
    protected $connection; 

    public function __construct($connection) 
    { 
     $this->connection = $connection; 
    } 
} 


class UserData extends BaseData 
{ 
    public function exists() 
    { 
     return is_connected($this->connection); 
    } 

    public function get() 
    { 
     return get_data($this->connection); 
    } 
} 

$oUserData = new UserData(new Connection()); 

А вот образец для [Реферат класса] -> [Class] без интерфейса

Abstract class BaseData 
{ 
    protected $connection; 

    public function __construct($connection) 
    { 
     $this->connection = $connection; 
    } 

    abstract public function connected(); 
    abstract public function get(); 
} 

class UserData extends BaseData 
{ 
    public function exists() 
    { 
     return is_connected($this->connection); 
    } 

    public function get() 
    { 
     return get_data($this->connection); 
    } 
} 

$oUserData = new UserData(new Connection()); 

Я в настоящее время создает небольшое приложение (может вырасти больше) и смущен о том, как реализовать вначале правильно.

Кстати, это объявление для __construct() с параметром, имеющим смысл в интерфейсе?

public function __construct($connection); 
+1

Интерфейсы и тезисы - это совершенно разные вещи с совершенно разными целями, поэтому вы не можете реально сравнивать их таким образом. –

+1

Я вижу различия, но не могу понять разницу в практическом смысле :(Потому что оба они работают если я хочу наследовать от одного интерфейса? Хотя он может реализоваться из нескольких интерфейсов, правильно? Спасибо! – user702300

+0

Мой плохой скриншот неправильного кода для второго примера –

ответ

9

Абстрактные классы определяют интерфейс, который должен быть реализован для наследников абстрактного класса. Interface-Construct определяет интерфейс, который должен реализовываться классом, который реализует конструкцию интерфейса, реализация интерфейса не ограничивается одним интерфейсом, тогда как наследование класса связано с одним (абстрактным) классом.

Интерфейсы в PHP намеренно используются для обозначения типов ограниченного подмножества всего интерфейса класса. Нет причин для интерфейса на абстрактных классах, поскольку их получатель экземпляров их наследников не использовал их (с типом или логической идентификацией над instanceof/is_a). Более ценным преимуществом интерфейсных конструкций является возможность замены общей реализации интерфейсов с альтернативной реализацией.

В случае вашего BaseData-примера я рекомендую отказаться от абстрактной идеи и использовать вместо нее характер и отдельные интерфейсы.

trait connectionBrokerConstructor { 
    protected $connection; 

    public function isConnected() 
    { 
     return $this->connection instanceof Connection; 
    } 

    public function setConnection(Connection $connection) 
    { 
     $this->connection = $connection; 
    } 
} 

interface connectable 
{ 
    public function setConnection(Connection $connection); 
    public function isConnected(); 
} 

interface userDataRepositoryInterface 
{ 
    public function get(); 
} 

class UserData implements connectable, userDataRepositoryInterface 
{ 
    use connectionBrokerConstructor; 

    public function __construct(Connection $connect = null) 
    { 
     $this->setConnection($connection); 
    } 

    public function get() 
    { 
     return array('something'); 
    } 
} 
+0

Спасибо, комбинация интерфейсов и использование черт - интересная идея. – user702300

+0

Обратите внимание, что для целей требуется PHP 5.4.0 или более – RightHandedMonkey

2

Действительно абстрактные классы и интерфейсы различны.

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

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

------- Редактировать с примером

Я не специалист в таких вещах, но я всегда просто сделать interface ->class.

Например, вот простой интерфейс:

interface AnimalInterface { 

    public function all(); 

    public function findBySlug($slug); 

} 

А вот это класс, который реализует этот интерфейс (упрощенно):

class AnimalEloquentRepository implements AnimalInterface { 

    public function all() 
    { 
    return Animal::all(); 
    } 

    public function findBySlug($slug) 
    { 
    return Animal::whereSlug($slug)->first(); 
    } 

} 

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

Я уверен, что есть лучшие способы сделать что-то, но в прошлом это работало очень хорошо.

+0

Но на основании приведенных выше примеров, с кем бы вы могли следовать и почему? – user702300

+0

Я исправил свой ответ с примером реального мира, который я использую. –

+0

Хорошо, спасибо за пример, как насчет определения __construct() в интерфейсе? Имеет ли смысл принудительно использовать его для передачи переменной параметра, например: public function __construct ($ connection); – user702300

0

Моя репутация не позволяет комментарии, но это заявление в ответ tr0y является вводящим в заблуждение:

«Абстрактные классы определяет интерфейс, который должен быть реализован к наследникам абстрактного класса.»

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

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

Другое отличие состоит в том, что методы в интерфейсе не могут иметь тело, тогда как методы в абстрактном классе должны иметь тело.

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