Можете ли вы помочь уточнить PHP интерфейс для меня. Я понял, что главное — чтобы несколько классов могли реализовывать одни и те же функции.
abstract class Plane {
public function openDoors();
}interface Fliers {
public function fly();
}
теперь давайте использовать их
class Boeing747 extends Plane implements Fliers {
public function fly() {
// some stuff
}
public function openDoors() {
// do something
}
}
а также
class Tweety implements Fliers{
public function fly() {
// some stuff
}
}
В этом случае и Boeing747, и Tweety могут реализовать интерфейс Fliers для доступа к публичной функции fly (). Однако во всех примерах, которые я вижу, функциональность в интерфейсе фактически не определяется, а только когда она вызывается внутри самого метода класса.
Почему бы мне не просто определить fly () как отдельную функцию в каждом из Boeing747 и Tweety вместо использования интерфейса? Можете ли вы привести конкретный, базовый пример, где это было бы выгодно? Спасибо!
Это техника, известная как Дизайн по контракту. По сути, интерфейс служит контрактом или обещанием, что любой класс, реализующий интерфейс, будет демонстрировать определенный набор поведений. Это позволяет вашему коду проверять возможности объекта, переданного ему, не беспокоясь о деталях, которые не имеют значения в текущем контексте. Например, ваш метод openDoors () может в равной степени применяться к дому, летательному аппарату, замку канала, автомобилю или чему-либо еще с дверями, но, кроме наличия дверей, все эти вещи имеют очень мало общего. Даже если они все поддерживают идею наличия дверей, которые можно открывать, они могут фактически выполнять действия по открытию двери совершенно разными способами.
Интерфейс позволяет сообщать вызывающему коду, что все эти вещи имеют двери, которые вы можете открыть, без необходимости устанавливать какие-либо искусственные отношения между ними, когда их нет. Ключевое слово instanceof позволяет проверить, соответствует ли объект определенным критериям (является ли он экземпляром определенного класса или подкласса или реализует ли он определенный интерфейс).
interface ThingWithDoors {
public function openDoors ();
}
class House implements ThingWithDoors {
// Implement openDoors here
}
class CanalLock implements ThingWithDoors {
// Implement openDoors here
}
class Boeing747 extends Aircraft implements ThingWithDoors {
// Implement openDoors here
}
// Calling code
if ($object instanceof ThingWithDoors) {
// We don't know exactly what class we have, but we do know it has an openDoors method
$object -> openDoors ();
}
Теоретически можно достичь того же с помощью других функций PHP, таких как method_exists или Reflection, но эти методы далеки от идеальных, поскольку нет контракта для принудительного применения чего-либо (два разных класса могли бы реализовывать открытие дверей, но иметь совершенно разные имена для методов, которые делают это, и вы должны проверить оба с вызовами method_exists). Затем, предположим, какой-то другой программист добавляет в систему новый класс, который реализует открытие дверей совершенно иначе, чем те, которые вы уже проверяли. Весь код, где двери могут быть открыты по всей программе, должен быть обновлен, чтобы учесть и этот новый метод! Если вы добавите новый класс в систему, и он реализует интерфейс ThingWithDoors, то весь код, открывающий двери, будет автоматически работать с новым классом, как это было со старым классом, без каких-либо изменений (при условии, что новый класс реализует). интерфейс правильно и учитывает возвращаемые значения, которые, к сожалению, не применяются интерфейсами PHP).
Еще одна приятная вещь для программистов заключается в том, что им не нужно постоянно искать в документации / исходном коде, как вызывать определенные поведения в объекте. Если они знают, как выглядит интерфейс ThingWithDoors, то они знают, что все, что реализует ThingWithDoors, может открыть свои двери, и что вызов метода для этого всегда будет openDoors (). Это может сэкономить вам немало времени как разработчику, особенно в большом проекте!
в OO PHP объект может иметь только один родительский класс. Чтобы понять, почему это принято, давайте использовать Птичий класс показать, что такое множественное наследование и как оно может привести к проблемам.
Если вы хотите создать Wooping_Crane класс, было бы разумно извлечь этот класс из класса Bird. Предположим, у вас также есть Endangered_Species class.
Множественное наследование позволит вам создать класс Wooping_Crane из комбинации этих двух классов (классы Bird и Endangered). Это может показаться отличной идеей, пока вы не поймете, что оба класса определяют пищевое поведение. Какой предпочесть? так что это недостаток множественного наследования.
PHP решает это двумя способами: во-первых, используя интерфейс — класс только с определением функции.
Если бы Endangered_Species были интерфейсом, а не классом, наличие более чем одной функции приема пищи не имело бы значения. Определение метода в классе Bird будет действовать как реализация функции интерфейса. Таким образом, интерфейсы избегают проблемы определения одной и той же функции дважды.
Во-вторых, используя черты. Вы можете прочитать об этом в других сообщениях.