W3docs

extends

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

Ключевое слово extends в PHP

extends — это способ объявить наследование в PHP: дочерний класс (или подкласс), созданный с помощью extends, автоматически получает все непривилегированные свойства и методы своего родителя (или суперкласса). Вместо того чтобы копировать общий код в каждый связанный класс, достаточно написать его один раз в родительском классе и позволить подклассам специализировать его.

На этой странице описываются синтаксис, вызов кода родителя через parent::, принцип работы переопределения методов, правила модификаторов доступа, определяющие, что наследует дочерний класс, а также типичные ошибки. PHP поддерживает только одиночное наследование — класс может расширять extends ровно один родительский класс (используйте интерфейсы, когда тип должен выполнять несколько ролей).

Синтаксис

class ChildClass extends ParentClass {
  // additional or overriding members
}

Дочерний класс может делать три вещи:

  1. Наследовать члены родителя без изменений.
  2. Добавлять новые собственные свойства и методы.
  3. Переопределять унаследованный метод, повторно объявив его с тем же именем.

Первый пример

<?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)
Result

Если бы у 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
Result

Полные правила 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 выдаст предупреждение.

Связанные темы

Практика

Практика
В чём значение ключевого слова 'extends' в PHP?
В чём значение ключевого слова 'extends' в PHP?
Was this page helpful?