Может ли класс расширять как класс, так и реализовывать интерфейс

100

Может ли класс расширять как интерфейс, так и другой класс в PHP?
В основном я хочу это сделать:

interface databaseInterface{
 public function query($q);
 public function escape($s);
 //more methods
}

class database{ //extends both mysqli and implements databaseInterface
 //etc.
}

Как бы это сделать, просто сделав:

class database implements databaseInterface extends mysqli{ 

приводит к фатальной ошибке:

Ошибка синтаксического анализа: синтаксическая ошибка, неожиданный T_EXTENDS, ожидание '{' в * файле * в строке * в строке *
Пим Ягер
источник
18
Как это слишком локализовано ?! «Этот вопрос вряд ли поможет будущим посетителям». Тем не менее, лучший ответ имеет 33 положительных голоса, а вопрос 4 звезды!
duality_

Ответы:

177

Попробуйте по-другому:

class database extends mysqli implements databaseInterface { ...}

Это должно работать.

Саймон Леманн
источник
Ах, спасибо большое. Почему именно должно быть наоборот?
Пим Ягер,
14
Поскольку вы можете унаследовать только один класс и реализовать любое количество интерфейсов, это, вероятно, было синтаксическим сахаром. Также помните, что если ваш подкласс реализует какие-либо интерфейсы, они также будут отображаться в списке реализованных методов. Так что расположение их в таком порядке имеет определенный смысл.
Дрю
Это плохая практика?
Мохаммед
21

Да, оно может. Вам просто нужно сохранить правильный порядок.

class database extends mysqli implements databaseInterface { ... }

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

Однако я чувствую себя обязанным предупредить вас, что расширение класса mysqli - невероятно плохая идея. . Само по себе наследование, вероятно, является наиболее переоцененным и неправильно используемым понятием в объектно-ориентированном программировании.

Вместо этого я бы посоветовал делать вещи, связанные с db, способом mysqli (или способом PDO).

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

Михал Рудницкий
источник
1
Почему расширение класса mysqli - плохая идея?
Пим Ягер,
11
Во-первых, потому что это не твое. Когда ребята из mysqli решат что-то изменить, поведение подкласса также изменится. Во-вторых, наследование используется для СПЕЦИАЛИЗАЦИИ, а не для РАСШИРЕНИЯ дополнительной функциональностью. Это наиболее неправильно понимаемая вещь в ООП. Как правило, я стараюсь расширять только абстрактные классы.
Michał Rudnicki,
Михал - чем изменение mysqli будет отличаться для разработчика, который использует полиморфный подход по сравнению с агрегированным / составным? Вам все равно придется обновить свой код, чтобы обработать изменения.
Питер Бейли,
2
Я знаком с шаблоном адаптера. Я просто говорю, что если имя метода изменится или станет устаревшим, вам все равно придется изменить код в обоих сценариях. Хотя я согласен с тем, что неполиморфный подход в этом сценарии лучше, я не верю в то, что адаптер будет «невосприимчивым» к изменениям.
Питер Бейли,
2
Вам нужно будет изменить только код адаптера, а не все места, где используется этот код. С помощью композиции вы можете обеспечить уровень совместимости несмотря ни на что, тогда как с наследованием вы можете назвать это в лучшем случае взломом. И, я поправлюсь, адаптер обеспечит лучшую невосприимчивость к изменениям.
Michał Rudnicki
6

да, на самом деле, если вы хотите реализовать несколько интерфейсов, вы можете сделать это так:

public class MyClass extends BaseClass implements myInterface1, myInterface2, myInterface3{ 

}
нулевой указатель
источник