Конструктор класса PHP в интерфейсе или классе
У меня возникли проблемы с мышлением о хорошей структуре для создания моих классов и объектов.
В приведенном ниже коде я использую интерфейс для определения методов класса, но также хочу передать соединение с базой данных с моим конструктором, чтобы класс имел это соединение для работы.
Правильно ли это, когда я закодировал его ниже, что конструктор помещен в мой класс и методы в моем интерфейсе?
interface IDataItem
{
public function saveItem(Item $theItem);
}
class DataItem implements IDataItem{
public function __construct(Database $database)
{
$this->database = $database;
}
public function saveItem(Item $item)
{
//save the item
}
}
$db = new Database(); //from a database class
$dataItem = new DataItem($db);
$dataItem->saveItem($anItem);
Ответы
Ответ 1
Я лично не думаю, что вы должны поместить конструктор в интерфейс, потому что вы никогда не создадите новый объект, вызвав конструктор, не зная о том, какую реализацию вы используете.
В вашем коде есть ошибка, метод в интерфейсе не может иметь реализацию, он должен быть просто объявлением, вроде этого
interface IDataItem
{
public function saveItem($theItem);
}
Ответ 2
Хотя технически возможно добавить конструктор в интерфейс, интерфейсы не должны определять конструктор, потому что это будет деталь реализации класса реализации. Интерфейс должен просто определить открытый API, к которому могут обратиться другие соавторы. То есть, они не должны обеспечивать выполнение конкретной реализации.
Если вы поместите конструктор с просьбой о подключении к базе данных в интерфейсе, вы должны ограничить конкретные классы зависимостями в сигнатуре конструктора. Если конкретный класс, реализующий интерфейс, нуждается в другом (поскольку он сохраняет в Webservice) или дополнительной (возможно, Logger) зависимости, вы не можете сделать это с вашим интерфейсом.
Ответ 3
Это немного не соответствует теме, но я думаю, что это подчеркивает случай, когда было бы полезно иметь конструктор, определенный в интерфейсе.
Можно создать экземпляр объекта, не зная его класса. Вот простой пример:
interface Animal
{
public function __construct($name);
public function speak();
public function getName();
}
class Cat implements Animal
{
protected $name=null;
public function __construct($name){ $this->name=$name; }
public function speak(){ echo 'meow'; }
public function getName(){ return $this->name;}
}
class Dog implements Animal
{
protected $name=null;
public function __construct($name){ $this->name=$name; }
public function speak(){ echo 'woof'; }
public function getName(){ return $this->name;}
}
$animals=Array(array('name'=>'Felix','type'=>'Cat'),array('name'=>'Fido','type'=>'Dog'));
foreach($animals as $a)
{
$theAnimal=new $a['type']($a['name']);
echo '<p>speak, '.$theAnimal->getName().'</p><p>';
$theAnimal->speak();
echo '</p>';
}
Я использовал что-то вроде этого для маршрутизации URL-адресов, чтобы сопоставлять URL-адреса своим контроллерам верхнего уровня.
Ответ 4
Интерфейсы - это всего лишь контракт на принудительное использование классов, которые могут быть несвязанными, будут реализовывать одни и те же методы.
Поскольку вы должны явно знать класс при его создании, бесполезно помещать конструктор в интерфейс. Вы никогда не вызовете конструктор через интерфейс. Ваше текущее решение верное.
Ответ 5
Сделайте переменную для хранения дескриптора db в вашем классе.