Menu
Coddy logo textTech

Переопределение методов

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

Иногда унаследованный метод родительского класса не совсем подходит для нужд дочернего класса. Переопределение методов (Method overriding) позволяет дочернему классу предоставить собственную реализацию метода, который уже существует в родительском классе.

Чтобы переопределить метод, просто определите метод в дочернем классе с тем же именем, что и метод родительского класса:

<?php
class Animal {
    public $name;
    
    public function __construct($name) {
        $this->name = $name;
    }
    
    public function speak() {
        return "$this->name makes a sound";
    }
}

class Cat extends Animal {
    public function speak() {
        return "$this->name says meow";
    }
}

$cat = new Cat("Whiskers");
echo $cat->speak();

Вывод:

Whiskers says meow

Класс Cat полностью заменяет родительский метод speak() своей собственной версией. Когда вы вызываете speak() у объекта cat, PHP использует реализацию дочернего класса.

Вы также можете расширить поведение родительского класса, комбинируя parent:: с вашей собственной логикой:

<?php
class Dog extends Animal {
    public function speak() {
        return parent::speak() . " - woof woof!";
    }
}

$dog = new Dog("Rex");
echo $dog->speak();

Вывод:

Rex makes a sound - woof woof!

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

challenge icon

Задание

Легко

Давайте создадим систему уведомлений, которая демонстрирует, как дочерние классы могут полностью заменять или расширять методы родительских классов с помощью переопределения методов.

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

  • Notification.php — Определите класс Notification, который служит базой для всех типов уведомлений. Он должен иметь публичное свойство $recipient и конструктор, который принимает и устанавливает получателя. Включите метод send($message), который возвращает "Sending to $this->recipient: $message".
  • UrgentNotification.php — Определите класс UrgentNotification, который расширяет Notification. Подключите файл Notification в начале. Этот класс должен полностью переопределить метод send($message), чтобы он возвращал "URGENT to $this->recipient: $message!!!" — обратите внимание на префикс "URGENT" и восклицательные знаки в конце. Это демонстрирует полную замену поведения родителя.
  • LoggedNotification.php — Определите класс LoggedNotification, который расширяет Notification. Подключите файл Notification в начале. Этот класс должен переопределить send($message), но основываться на реализации родителя: вызовите parent::send($message) и добавьте " [logged]" к результату. Это демонстрирует расширение, а не замену поведения.

В main.php подключите все три файла классов уведомлений. Вы получите два входных значения: имя получателя и сообщение для отправки. Создайте по одному экземпляру каждого типа уведомления (все используют одного и того же получателя), затем вызовите send() с сообщением для каждого из них. Выведите каждый результат на отдельной строке в следующем порядке: обычное уведомление, срочное уведомление, а затем логируемое уведомление.

Эта задача показывает оба подхода к переопределению методов — UrgentNotification полностью заменяет логику родителя своим собственным форматированием, в то время как LoggedNotification использует parent::, чтобы сохранить исходное поведение и дополнить его.

Шпаргалка

Переопределение методов позволяет дочернему классу предоставить собственную реализацию метода, унаследованного от родительского класса.

Чтобы переопределить метод, определите в дочернем классе метод с тем же именем, что и метод родителя:

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

class Cat extends Animal {
    public function speak() {
        return "says meow";
    }
}

Дочерний класс полностью заменяет реализацию метода родителя. При вызове для дочернего объекта PHP использует версию дочернего класса.

Чтобы расширить поведение родителя вместо его замены, используйте parent:: для вызова родительского метода и добавьте свою собственную логику:

<?php
class Dog extends Animal {
    public function speak() {
        return parent::speak() . " - woof woof!";
    }
}

Это объединяет исходное поведение родителя с дополнительной функциональностью дочернего класса.

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

<?php

require_once 'Notification.php';
require_once 'UrgentNotification.php';
require_once 'LoggedNotification.php';

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

// TODO: Создать по одному экземпляру каждого типа уведомления (все используют одного и того же получателя)

// TODO: Вызвать метод send() с сообщением для каждого уведомления
// Вывести каждый результат на отдельной строке в следующем порядке:
// 1. Обычное уведомление
// 2. Срочное уведомление
// 3. Логируемое уведомление

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

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

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