This article has been localized into Russian by the community.
Абстрактные классы
Абстрактные (abstract) классы особенные, т.к. для них нельзя создавать экземпляры. Вместо этого они обычно содержат функции, которые наследуются в новые классы. Поэтому они часто используются как базовые классы для какой-нибудь большой иерархии классов. В параграфе про наследование мы создали класс Animal (Животное), а затем класс Dog (Собака), который наследовался от Animal. В вашем проекте вы можете небезосновательно решить, что нельзя создавать экземпляры Animal, поскольку он слишком неконкретный, а можно использовать только классы-наследники. Тогда класс Animal будет базовым классом в вашем маленьком зоопарке.
Абстрактным может быть также отдельный метод. Но если вы отметите хотя бы одну функцию в классе как абстрактную, то и весь класс должен быть абстрактным - только абстрактные классы могут содержать абстрактные методы. Следующая особенность - абстрактные функции не содержат (и не могут содержать) никакого кода, это просто объявление. Они нужны лишь затем, чтобы принудить любой класс-наследник реализовать данную функцию и написать подходящий код. Иначе PHP выбросит ошибку. Тем не менее, абстрактные классы могут содержать не абстрактные методы, которые реализуют базовую функциональность в абстрактном классе. Давайте продолжим разбираться на примере абстрактного класса:
abstract class Animal
{
public $name;
public $age;
public function Describe()
{
return $this->name . ", " . $this->age . " years old";
}
abstract public function Greet();
}
Как вы можете видеть, класс выглядит как обычно, за исключением пары деталей. Первая - это ключевое слово abstract, которое отмечает и класс в целом, и последнюю функцию как абстрактные. Как уже упоминалось, абстрактная функция не может иметь тела (кода), так что она просто заканчивается точкой с запятой. Теперь давайте создадим наследника для нашего класса Animal:
class Dog extends Animal
{
public function Greet()
{
return "Woof!";
}
public function Describe()
{
return parent::Describe() . ", and I'm a dog!";
}
}
Как вы можете видеть, мы реализовали обе функции базового класса Animal. Функция Greet(), которую мы были обязаны реализовать, т.к. она была отмечена как абстрактная, - она просто возвращает слово/звук, свойственное данному виду животных. Мы не обязаны были реализовывать функцию Describe() - она уже реализована в класса Animal, но нам захотелось немного расширить ее функциональность. Здесь есть вкусная возможность - мы можем переиспользовать код, который уже реализовали в классе Animal, и добавить к нему, что захотим. В нашем случае мы используем ключевое слово parent (родитель), чтобы обратиться к классу Animal, а затем вызываем функцию Describe() из этого класса. После этого мы добавляем небольшой текст к результату, чтобы уточнить, о каком виде животного идет речь. Теперь давайте попробуем использовать этот новый класс:
$animal = new Dog();
$animal->name = "Bob";
$animal->age = 7;
echo $animal->Describe();
echo $animal->Greet();
Тут нет ничего загадочного. Мы просто создаем экземпляр класса Dog, задаем два его свойства и затем вызываем два метода, определенных в этом классе. Если вы протестируете этот код, то увидите, что метод теперь содержит комбинацию из версий для Animal и Dog, как мы и ожидали.