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

Предположим, что есть родительский класс, содержащий определенный метод, например drive. Есть два дочерних класса, класс 1 и класс 2, и каждый из них расширяет родительский класс. Они наследуют метод привода и переопределяют его.

Итак, PHP не поддерживает то, о чем я собираюсь вам рассказать, поскольку это проблема множественного наследования. Другой класс, класс 3, расширяет как класс 1, так и класс 2. Как он узнает, какой метод привода использовать? Какой метод он будет наследовать? То ли из 1 класса, то ли из 2 класса.

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

Резюме: мы давно не проводили занятия по автомобилям. Давайте посмотрим на те, которые мы будем делать.

  • "Машина"
  • "Транспортное средство"

Для начала давайте создадим наш тестовый файл.

Наш класс Car расширяет класс Vehicle, что означает, что он наследует все свойства и методы класса Vehicle. Сам класс Car имеет несколько констант, свойств и методов. Большинство методов являются просто геттерами и сеттерами, за исключением нескольких методов, таких как turnOn() и turnOff().

Если мы отступим назад и начнем думать о том, что есть у каждого автомобиля с бензиновым двигателем, это двигатель и трансмиссия. Вместо того, чтобы загружать все в наш класс Car, мы создадим отдельные классы Engine и Transmission. Почему двигатель и трансмиссия? Мы можем пройти через все в машине, но мы просто выбрали это в качестве простых примеров.

На самом деле любой объект внутри автомобиля может иметь свой собственный класс со свойствами. Подумайте о сиденье в машине. Он представляет определенный объект. У него есть определенные детали, такие как размеры и тип материала, поэтому он должен быть отдельным отдельным объектом. Мы хотим использовать этот объект и реализовать его в нашем классе Car. Несмотря на то, что наследовать свойства от Seat не имеет смысла, даже если бы мы это сделали, мы не смогли бы расширить несколько классов. Просто чтобы убедиться в этом, давайте попробуем.

Если бы мы хотели расширить класс Engine, мы не могли бы сделать что-то вроде этого:

class Car extends Vehicle, Engine { … }

Ваш редактор автоматически выделит Engine и скажет, что это неправильный синтаксис. Так что мы можем сделать? Сначала давайте добавим метод к классу Engine и изменим класс на Trait, поскольку технически Engine — это черта автомобиля.

Давайте сделаем то же самое для нашей Трансмиссии.

Черты Engine и Transmission имеют одинаковое имя метода, check_oil_level(). Метод признаков двигателя возвращает «уровень масла в двигателе в норме», а метод признаков трансмиссии возвращает «уровень трансмиссионного масла в норме».

Отлично, как теперь мы можем использовать трейты в нашем классе Car? С помощью ключевого слова использовать. Давайте начнем с этого, как обычно, и начнем с простого, реализовав свойство Transmission и проверив уровень трансмиссионного масла.

Мы должны получить следующий ответ: «Уровень трансмиссионного масла хороший».

Мы по-прежнему можем вызывать методы из нашего родительского класса Vehicle, вызывая имя метода, как обычно.

echo $subaru->getYear(); // example from Parent class

Давайте перейдем к следующему шагу, добавив наш трейт Engine в класс Car.

use Transmission, Engine;

Мы получаем следующую ошибку: Метод признака 'check_oil_level' не будет применен, так как он конфликтует с 'Передачей'.Если вы все еще хотите попробовать, обновите страницу, и вы получите следующая ошибка.

Как мы обойдем это? Мы должны указать PHP, какой метод check_oil_level() мы хотим использовать. Как мы можем сделать это? Со специальным синтаксисом. После того как вы используете оба признака, добавьте фигурные скобки и используйте ключевое слово вместо. Я хочу использовать этот метод вместоэтого другого метода.

Теперь, когда мы вызываем check_oil_level(), PHP знает, какой метод вызывать. Отлично, это решает одну проблему. Но что, если мы также хотим проверить моторное масло? Вам просто нужно переименовать один из них в классе Car. Наша передача check_oil_level() будет использоваться по умолчанию. Наша проверка моторного масла будет называться check_engine_oil_level().

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



Дино Кайич в настоящее время является руководителем отдела информационных технологий в компаниях LSBio (LifeSpan BioSciences, Inc.), Absolute Antibody, Kerafast, Everest BioTech, Nordic MUbio и Exalpha. Он также является генеральным директором MyAutoSystem. Он имеет более чем десятилетний опыт разработки программного обеспечения. У него есть B.S. в области компьютерных наук и несовершеннолетнего в области биологии. Его опыт включает в себя создание приложений для электронной коммерции на уровне предприятия, разработку программного обеспечения на основе исследований и содействие распространению знаний посредством письма.

Вы можете связаться с ним в LinkedIn, подписаться на него в Instagram, подписаться на его блог или подписаться на его публикацию на Medium.

Прочитайте все истории Дино Каджика (и тысяч других авторов на Medium). Ваш членский взнос напрямую поддерживает Дино Кайича и других писателей, которых вы читаете. Вы также получите полный доступ ко всем историям на Medium.