Абстрактные классы - это классы, которые содержат один или несколько абстрактных методов. Абстрактный метод - это метод, который объявлен, но не содержит реализации. Абстрактные классы не могут быть созданы, и требуют, чтобы подклассы обеспечивали реализации для абстрактных методов.
1. Не может быть создан экземпляр абстрактного класса : классы, определенные как абстрактные, не могут быть созданы, и любой класс, содержащий хотя бы один абстрактный метод, также должен быть абстрактным.
Пример ниже:
abstract class AbstractClass
{
abstract protected function getValue();
abstract protected function prefixValue($prefix);
public function printOut() {
echo "Hello how are you?";
}
}
$obj=new AbstractClass();
$obj->printOut();
//Fatal error: Cannot instantiate abstract class AbstractClass
2. Любой класс, который содержит хотя бы один абстрактный метод, также должен быть абстрактным : абстрактный класс может иметь абстрактные и неабстрактные методы, но он должен содержать хотя бы один абстрактный метод. Если у класса есть хотя бы один абстрактный метод, то этот класс должен быть объявлен как абстрактный.
Примечание: Черты поддерживают использование абстрактных методов для наложения требований на выставляющий класс.
Пример ниже:
class Non_Abstract_Class
{
abstract protected function getValue();
public function printOut() {
echo "Hello how are you?";
}
}
$obj=new Non_Abstract_Class();
$obj->printOut();
//Fatal error: Class Non_Abstract_Class contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (Non_Abstract_Class::getValue)
3. Абстрактный метод не может содержать тело : методы, определенные как абстрактный, просто объявляют сигнатуру метода - они не могут определять реализацию. Но неабстрактный метод может определять реализацию.
abstract class AbstractClass
{
abstract protected function getValue(){
return "Hello how are you?";
}
public function printOut() {
echo $this->getValue() . "\n";
}
}
class ConcreteClass1 extends AbstractClass
{
protected function getValue() {
return "ConcreteClass1";
}
public function prefixValue($prefix) {
return "{$prefix}ConcreteClass1";
}
}
$class1 = new ConcreteClass1;
$class1->printOut();
echo $class1->prefixValue('FOO_') ."\n";
//Fatal error: Abstract function AbstractClass::getValue() cannot contain body
4. При наследовании от абстрактного класса все методы, помеченные как абстрактные в объявлении класса родителя, должны быть определены дочерним элементом : если вы наследуете абстрактный класс, вы должны предоставить реализации для всех абстрактных методов в нем.
abstract class AbstractClass
{
// Force Extending class to define this method
abstract protected function getValue();
// Common method
public function printOut() {
print $this->getValue() . "<br/>";
}
}
class ConcreteClass1 extends AbstractClass
{
public function printOut() {
echo "dhairya";
}
}
$class1 = new ConcreteClass1;
$class1->printOut();
//Fatal error: Class ConcreteClass1 contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (AbstractClass::getValue)
5. Та же (или менее ограниченная) видимость : при наследовании от абстрактного класса все методы, помеченные как абстрактные в объявлении класса родителя, должны быть определены дочерним элементом; Кроме того, эти методы должны быть определены с одинаковой (или менее ограниченной) видимостью. Например, если абстрактный метод определен как защищенный, реализация функции должна быть определена как защищенная или общедоступная, но не закрытая.
Обратите внимание, что абстрактный метод не должен быть закрытым.
abstract class AbstractClass
{
abstract public function getValue();
abstract protected function prefixValue($prefix);
public function printOut() {
print $this->getValue();
}
}
class ConcreteClass1 extends AbstractClass
{
protected function getValue() {
return "ConcreteClass1";
}
public function prefixValue($prefix) {
return "{$prefix}ConcreteClass1";
}
}
$class1 = new ConcreteClass1;
$class1->printOut();
echo $class1->prefixValue('FOO_') ."<br/>";
//Fatal error: Access level to ConcreteClass1::getValue() must be public (as in class AbstractClass)
6. Сигнатуры абстрактных методов должны совпадать : при наследовании от абстрактного класса все методы, помеченные как абстрактные в объявлении класса родителя, должны быть определены потомком, сигнатуры методов должны совпадать, то есть подсказки типа и число обязательные аргументы должны быть одинаковыми. Например, если дочерний класс определяет необязательный аргумент, а сигнатура абстрактного метода - нет, в сигнатуре нет конфликта.
abstract class AbstractClass
{
abstract protected function prefixName($name);
}
class ConcreteClass extends AbstractClass
{
public function prefixName($name, $separator = ".") {
if ($name == "Pacman") {
$prefix = "Mr";
} elseif ($name == "Pacwoman") {
$prefix = "Mrs";
} else {
$prefix = "";
}
return "{$prefix}{$separator} {$name}";
}
}
$class = new ConcreteClass;
echo $class->prefixName("Pacman"), "<br/>";
echo $class->prefixName("Pacwoman"), "<br/>";
//output: Mr. Pacman
// Mrs. Pacwoman
7. Абстрактный класс не поддерживает множественное наследование : Абстрактный класс может расширять другой абстрактный класс, Абстрактный класс может обеспечивать реализацию интерфейса. Но он не поддерживает множественное наследование.
interface MyInterface{
public function foo();
public function bar();
}
abstract class MyAbstract1{
abstract public function baz();
}
abstract class MyAbstract2 extends MyAbstract1 implements MyInterface{
public function foo(){ echo "foo"; }
public function bar(){ echo "bar"; }
public function baz(){ echo "baz"; }
}
class MyClass extends MyAbstract2{
}
$obj=new MyClass;
$obj->foo();
$obj->bar();
$obj->baz();
//output: foobarbaz
Примечание. Обратите внимание: порядок или расположение классов в вашем коде могут повлиять на интерпретатор и привести к фатальной ошибке.
Поэтому при использовании нескольких уровней абстракции будьте осторожны с расположением классов в исходном коде.
приведенный ниже пример вызовет Неустранимая ошибка: класс 'лошадь' не найден
class cart extends horse {
public function get_breed() { return "Wood"; }
}
abstract class horse extends animal {
public function get_breed() { return "Jersey"; }
}
abstract class animal {
public abstract function get_breed();
}
$cart = new cart();
print($cart->get_breed());