Menu
Coddy logo textTech

Снова о переопределении методов

Часть раздела Объектно-ориентированное программирование путешествия по PHP на Coddy — урок 33 из 91.

Вы уже узнали о переопределении методов в главе «Наследование». Теперь давайте изучим, как это связано с полиморфизмом — одной из самых мощных концепций объектно-ориентированного программирования.

Полиморфизм означает «много форм». Когда вы переопределяете метод в дочернем классе, вы придаете этому методу другую форму, сохраняя при этом то же имя. Магия происходит тогда, когда вы работаете с объектами через их родительский тип:

<?php
class Animal {
    public function speak() {
        return "Some sound";
    }
}

class Dog extends Animal {
    public function speak() {
        return "Woof!";
    }
}

class Cat extends Animal {
    public function speak() {
        return "Meow!";
    }
}

function makeAnimalSpeak(Animal $animal) {
    return $animal->speak();
}

echo makeAnimalSpeak(new Dog()) . "\n";
echo makeAnimalSpeak(new Cat());

Вывод:

Woof!
Meow!

Функция makeAnimalSpeak() принимает любой Animal. Она не знает и ей не важно, получает ли она Dog или Cat. PHP автоматически вызывает правильный переопределенный метод на основе фактического типа объекта во время выполнения.

Это полиморфизм в действии.

Этот подход позволяет писать гибкий код, который работает с семейством связанных объектов, не зная их конкретных типов. Вы сможете добавить новые классы животных позже, и функция будет работать с ними автоматически.

Ключевой момент: Переопределение методов обеспечивает полиморфизм, позволяя различным классам по-разному реагировать на один и тот же вызов метода, который определяется во время выполнения фактическим типом объекта.

challenge icon

Задание

Легко

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

Вы организуете свой код в четырех файлах:

  • Instrument.php — Создайте класс Instrument с защищенным свойством $name, устанавливаемым через конструктор. Добавьте метод play(), который возвращает "[name] makes a sound". Это послужит базовым поведением, которое дочерние классы будут переопределять.
  • Guitar.php — Создайте класс Guitar, который расширяет Instrument. Подключите родительский файл. Конструктор принимает имя и передает его в родительский конструктор. Переопределите метод play(), чтобы он возвращал "[name] strums a chord".
  • Drum.php — Создайте класс Drum, который расширяет Instrument. Подключите родительский файл. Конструктор принимает имя и передает его в родительский конструктор. Переопределите метод play(), чтобы он возвращал "[name] beats a rhythm".
  • main.php — Подключите файлы Guitar и Drum. Создайте функцию с именем performWith, которая принимает параметр типа Instrument (с указанием типа) и возвращает результат вызова play() для него. Эта функция демонстрирует полиморфизм — она работает с любым типом инструмента благодаря указанию типа родительского класса.

Вы получите два входных значения: имя для гитары и имя для барабана. Создайте объекты Guitar и Drum с этими именами. Передайте каждый из них в функцию performWith() и выведите результаты — сначала для гитары, затем для барабана, каждый на новой строке.

Обратите внимание, как performWith() принимает любой Instrument, но PHP автоматически вызывает правильный переопределенный метод play() в зависимости от фактического типа объекта во время выполнения. Это и есть полиморфизм в действии!

Шпаргалка

Полиморфизм означает «много форм» и позволяет объектам разных классов обрабатываться через их родительский тип, сохраняя при этом их специфическое поведение.

Когда вы переопределяете метод в дочерних классах, PHP автоматически вызывает правильную версию на основе фактического типа объекта во время выполнения:

<?php
class Animal {
    public function speak() {
        return "Some sound";
    }
}

class Dog extends Animal {
    public function speak() {
        return "Woof!";
    }
}

class Cat extends Animal {
    public function speak() {
        return "Meow!";
    }
}

function makeAnimalSpeak(Animal $animal) {
    return $animal->speak();
}

echo makeAnimalSpeak(new Dog()); // Woof!
echo makeAnimalSpeak(new Cat()); // Meow!

Функция makeAnimalSpeak() принимает любой тип Animal через указание типа параметра. Ей не нужно знать конкретный класс — PHP определяет, какой переопределенный метод вызвать во время выполнения, основываясь на фактическом типе объекта.

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

Попробуйте сами

<?php
// Подключите файлы инструментов
require_once 'Guitar.php';
require_once 'Drum.php';

// Чтение входных данных
$guitarName = trim(fgets(STDIN));
$drumName = trim(fgets(STDIN));

// TODO: Создайте функцию performWith, которая:
// - Принимает параметр Instrument (используйте подсказку типа: Instrument $instrument)
// - Возвращает результат вызова play() на инструменте

// TODO: Создайте Guitar с $guitarName и Drum с $drumName
// TODO: Передайте каждый в performWith() и выведите результаты (сначала гитару, затем барабан)

?>
quiz iconПроверьте себя

В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.

Все уроки раздела Объектно-ориентированное программирование