Наследование в PHP

Наследование в PHP: extends, переопределение методов, parent::__construct(), final-классы и методы.

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

Extends

Дочерний класс объявляется с ключевым словом extends:

<?php
class Animal {
    public function __construct(
        protected string $name,
    ) {}

    public function speak(): string {
        return "{$this->name} издаёт звук";
    }

    public function getInfo(): string {
        return "Животное: {$this->name}";
    }
}

class Dog extends Animal {
    public function speak(): string {
        return "{$this->name} говорит: Гав!"; // переопределяем метод
    }

    public function fetch(): string {
        return "{$this->name} принёс мяч";     // новый метод
    }
}

$dog = new Dog("Шарик");
echo $dog->speak();   // Шарик говорит: Гав!
echo $dog->getInfo(); // Животное: Шарик
echo $dog->fetch();   // Шарик принёс мяч

Вывод:

Шарик говорит: Гав!
Животное: Шарик
Шарик принёс мяч

Вызов родительского конструктора

Если дочерний класс объявляет конструктор, нужно вручную вызвать конструктор родителя через parent::__construct():

<?php
class Animal {
    public function __construct(protected string $name) {}
}

class Dog extends Animal {
    public function __construct(string $name, private string $breed) {
        parent::__construct($name); // сначала инициализируем родителя
    }

    public function info(): string {
        return "{$this->name} ({$this->breed})";
    }
}

$dog = new Dog("Шарик", "Лабрадор");
echo $dog->info(); // Вывод: Шарик (Лабрадор)

Вывод:

Шарик (Лабрадор)

Переопределение метода и parent::

При переопределении метода можно вызвать версию родителя через parent::метод() — это удобно, когда нужно расширить поведение, а не заменить его полностью:

<?php
class Animal {
    protected string $name;

    public function __construct(string $name) {
        $this->name = $name;
    }

    public function describe(): string {
        return "Имя: {$this->name}";
    }
}

class Cat extends Animal {
    public function __construct(string $name, private string $color) {
        parent::__construct($name);
    }

    public function describe(): string {
        return parent::describe() . ", цвет: {$this->color}"; // дополняем
    }
}

$cat = new Cat("Мурка", "серая");
echo $cat->describe();

Вывод:

Имя: Мурка, цвет: серая

Запрет наследования: final

Ключевое слово final запрещает наследование класса или переопределение метода:

<?php
class Vehicle {
    final public function identify(): string {
        return "Это транспортное средство";
    }
}

class Car extends Vehicle {
    // public function identify(): string { ... } // Fatal error!
}

final class Singleton {
    // этот класс нельзя расширить
}

Используйте final осознанно: когда нужно гарантировать, что поведение класса не изменится. Чрезмерное применение затрудняет тестирование.

Коротко

  • extends — дочерний класс наследует все свойства и методы родителя.
  • Переопределяйте методы, объявляя их заново в дочернем классе.
  • parent::__construct() — вызов конструктора родителя; обязателен, если у дочернего класса есть свой конструктор.
  • parent::метод() — вызов родительской реализации метода из дочернего.
  • final class нельзя расширить; final function нельзя переопределить.
Проверьте себя
1. Как в дочернем классе вызвать конструктор родительского класса?
Asuper()
Bparent::__construct()
Cbase::__construct()
D__parent()
2. Что произойдёт, если попытаться унаследоваться от final-класса?
AНаследование произойдёт, но final-методы не перекроются
BPHP покажет предупреждение, но продолжит работу
CFatal error: Cannot extend final class
DДочерний класс станет тоже final
3. Может ли дочерний класс PHP расширять несколько родительских классов одновременно?
AДа: class A extends B, C {}
BНет: PHP поддерживает только одиночное наследование
CДа, но только абстрактных классов
DДа, через запятую до 3 классов
Поддержать проект