extends
Ключевое слово extends в PHP позволяет дочернему классу наследовать свойства и методы родительского класса в объектно-ориентированном программировании.
Ключевое слово extends в PHP
extends — это способ объявить наследование в PHP: дочерний класс (или подкласс), созданный с помощью extends, автоматически получает все непривилегированные свойства и методы своего родителя (или суперкласса). Вместо того чтобы копировать общий код в каждый связанный класс, достаточно написать его один раз в родительском классе и позволить подклассам специализировать его.
На этой странице описываются синтаксис, вызов кода родителя через parent::, принцип работы переопределения методов, правила модификаторов доступа, определяющие, что наследует дочерний класс, а также типичные ошибки. PHP поддерживает только одиночное наследование — класс может расширять extends ровно один родительский класс (используйте интерфейсы, когда тип должен выполнять несколько ролей).
Синтаксис
class ChildClass extends ParentClass {
// additional or overriding members
}Дочерний класс может делать три вещи:
- Наследовать члены родителя без изменений.
- Добавлять новые собственные свойства и методы.
- Переопределять унаследованный метод, повторно объявив его с тем же именем.
Первый пример
<?php
class Fruit {
public $name;
public $color;
public function __construct($name, $color) {
$this->name = $name;
$this->color = $color;
}
public function getInfo() {
echo "This fruit is a {$this->name} and it is {$this->color}.";
}
}
// Apple inherits everything from Fruit and overrides getInfo().
class Apple extends Fruit {
public function getInfo() {
echo "This fruit is an {$this->name} and it is {$this->color}.";
}
}
$apple = new Apple("apple", "red");
$apple->getInfo();
// Output: This fruit is an apple and it is red.Apple никогда не объявляет $name, $color или конструктор — они наследуются от Fruit. Класс только переопределяет getInfo(), что переопределяет версию родителя.
Вызов родителя через parent::
Дочерний класс нередко хочет расширить поведение родителя, а не заменить его. Когда дочерний класс определяет собственный конструктор, PHP не вызывает конструктор родителя автоматически — его нужно вызвать явно с помощью parent::__construct(). Тот же синтаксис parent:: работает для любого переопределённого метода.
<?php
class Car {
public $model;
public $year;
public function __construct($model, $year) {
$this->model = $model;
$this->year = $year;
}
public function getInfo() {
echo "This car is a {$this->model} from {$this->year}.";
}
}
class Toyota extends Car {
public function __construct($year) {
// Fill in the model, defer the rest to the parent.
parent::__construct("Toyota", $year);
}
public function getInfo() {
parent::getInfo(); // reuse the parent's output...
echo " (built by Toyota)"; // ...then add to it.
}
}
$toyota = new Toyota(2021);
$toyota->getInfo();
// Output: This car is a Toyota from 2021. (built by Toyota)Если бы у Toyota не было конструктора вовсе, она унаследовала бы конструктор Car, и объект создавался бы через new Toyota("Corolla", 2021).
Что дочерний класс может — и не может — наследовать
Модификаторы доступа определяют видимость через границу наследования:
- Члены
publicнаследуются и доступны везде. - Члены
protectedнаследуются и доступны внутри дочернего класса, но не снаружи. - Члены
privateне доступны в дочернем классе. Они всё ещё существуют на объекте, но дочерний класс не может обращаться к ним по имени.
<?php
class Account {
public $owner = "Ann";
protected $balance = 100; // visible to children
private $pin = "1234"; // hidden from children
public function reveal() {
return "$this->owner, balance $this->balance, pin $this->pin";
}
}
class SavingsAccount extends Account {
public function summary() {
// $this->balance works (protected); $this->pin would be null/undefined.
return "{$this->owner} has {$this->balance}";
}
}
$s = new SavingsAccount();
echo $s->summary();
// Output: Ann has 100Полные правила public / protected / private смотрите в разделе модификаторы доступа PHP.
Запрет расширения с помощью final
Используйте ключевое слово final, чтобы запретить дальнейшее расширение. Класс final class не может быть родительским; метод final не может быть переопределён подклассом. Это полезно, когда переопределение нарушило бы инвариант, на котором основывается класс.
class PaymentGateway {
final public function charge() { /* must not be altered */ }
}Распространённые ошибки
- Забытый
parent::__construct(). Определение конструктора дочернего класса затеняет конструктор родителя. Если забыть его вызвать, свойства родителя останутся неинициализированными. - Одиночное наследование.
class A extends B, C— синтаксическая ошибка. Для составного поведения используйте интерфейсы или трейты. - Приватные члены не передаются. Свойство
privateродителя невидимо для дочернего класса; сделайте егоprotected, если подклассам нужен доступ. - Сигнатуры переопределений должны оставаться совместимыми. Переопределяющий метод должен принимать те же (или более широкие) аргументы, иначе PHP выдаст предупреждение.
Связанные темы
- Наследование PHP — более широкая концепция, реализуемая через
extends. - Классы и объекты PHP — строительные блоки.
- Абстрактные классы — родители, которые должны быть расширены.
- Интерфейсы — контракты для несвязанных классов.