Что такое абстрактный класс php
Абстрактный класс представляет частичную реализацию для классов-наследников.
Абстрактный класс определяется с помощью модификатора abstract , который ставится перед именем класса:
abstract class Messenger
Одной из ключевых особенностей абстрактных классов является то, что мы не можем напрямую создать объекты абстрактного класса с помощью вызова его конструктора:
abstract class Messenger < >$telegram = new Messenger(); // эта строка не будет работать
Абстрактные классы, как и обычные классы, могут определять переменные и константы, методы и конструкторы.
Но другой особенностью абстрактных классов является то, что они могут содержать абстрактные методы. Это методы, которые не имеют реализации. Реализацию для них предоставляют классы-наследники. Например:
abstract class Messenger < abstract function send($message); // абстрактный метод >
При определении абстрактного метода перед словом function ставится модификатор abstract . А после списка параметров метода — точка с запятой.
Абстрактные методы могут размещаться только в абстрактных классах. Обычный неабстрактный класс не может иметь абстрактных методов.
Если неабстрактный класс наследуется от абстрактного класса, то он обязан реализовать все его абстрактные методы.
Для наследования классом абстрактного класса, как и в общем случае при наследовании, применяется ключевое слово extends . Например:
name = $name; > abstract function send($message); function close() < echo "Выход из мессенджера. "; >> class EmailMessenger extends Messenger < function send($message) < echo "$this->name отправляет сообщение: $message
"; > > $outlook = new EmailMessenger("Outlook"); $outlook->send("Hello PHP 8"); $outlook -> close(); ?> ?>
В данном случае класс EmailMessenger наследуется от абстрактного класса Messenger.
Абстрактный класс определяет абстрактный метод send() , поэтому класс-наследник EmailMessenger должен предоставить реализацию для этого метода.
Так, в данном случае мы получим следующий вывод:
Outlook отправляет сообщение: Hello PHP 8 Выход из мессенджера.
Можно заметить, что абстрактные классы похожи на интерфейсы — и те, и другие могут определять методы без реализации, которые реализуются в других классах. Однако, абстрактные классы, как и обычные классы, могут иметь переменные, неабстрактные методы, конструкторы с реализацией, а интерфейсы нет. Кроме того, в PHP один класс может наследоваться только от одного класса, тогда как один класс может применять сразу несколько интерфейсов.
PHP. ООП. Абстрактные классы и интерфейсы
В сегодняшнем уроке мы рассмотрим абстрактные классы и интерфейсы в php, а также обсудим различия между ними.
Абстрактные классы в php реализуются добавлением ключевого слово abstract. Абстрактные классы могут иметь свойства и методы. Но в отличии от обычных классов, методы в абстрактных классах не имеют тела. Ключевое значение в таких методах — необходимость их реализации в дочерних классах.
Интерфейс — это тот же абстрактный класс, но у него нет свойств. Интерфейс объявляется при помощи ключевого слова interface.
Еще одной важной особенностью является то, что класс может унаследовать только один класс, но может реализовывать сколь угодно много интерфейсов.
Различие в применении абстрактного класса и интерфейса — очень тонкий вопрос. Абстрактный класс скорее служит для объединения семейства классов. Например, есть абстрактный класс Автомобиль, и от него наследуются классы Ford, Toyota, у которых есть общие методы (объявленные в абстрактном классе).
Но если появляется класс Велосипед, то в нем нет смысла реализовывать, например, метод ПоменятьМасло. Для таких классов лучше описывать интерфейсы.
Код урока (абстрактный класс)
> class Car extends Transport < public $wheels = 4; public function countWheels() < echo "У машины " . $this->wheels . » колеса»; > public function driverSide() < echo $this->driverName . » сидит за рулем слева»; > public function changeOil() < echo "В машине надо обязательно менять масло"; >> class Bike extends Transport < public $wheels = 2; public function countWheels() < echo "У велосипеда " . $this->wheels . » колеса»; > public function driverSide() < echo $this->driverName . » просто сидит за рулем»; > public function changeOil() < echo "В велосипеде надо обязательно менять масло. Да ладно?"; >> $car = new Car(); $bike = new Bike(); /*Посмотрим на объекты*/ echo «
"; print_r($car); echo "
«; echo «
"; print_r($bike); echo "
«; $car->countWheels(); echo «
«; $bike->countWheels(); echo «
«; $car->driverSide(); echo «
«; $bike->driverSide(); echo «
«; $car->changeOil(); echo «
«; $bike->changeOil(); echo «
«; $car->sayHello(); echo «
«; $bike->sayHello();
Код урока (интерфейс)
interface Doorable < public function countDoors(); >class Car implements Oilable, Doorable < public $wheels = 4; public function countWheels() < echo "У машины " . $this->wheels . » колеса»; > public function changeOil() < echo "Пора менять масло"; >public function countDoors() < echo "В машине 2 или 4 двери"; >> class Bike < public $wheels = 2; public function countWheels() < echo "У велосипеда " . $this->wheels . » колеса»; > > $car = new Car(); $bike = new Bike(); /*Посмотрим на объекты*/ echo «
"; print_r($car); echo "
«; echo «
"; print_r($bike); echo "
«; $car->countWheels(); echo «
«; $bike->countWheels(); echo «
«; $car->changeOil(); echo «
«; $car->countDoors();
Что такое абстрактный класс php
This example will hopefully help you see how abstract works, how interfaces work, and how they can work together. This example will also work/compile on PHP7, the others were typed live in the form and may work but the last one was made/tested for real:
// Define things a product *has* to be able to do (has to implement)
interface productInterface public function doSell ();
public function doBuy ();
>
// Define our default abstraction
abstract class defaultProductAbstraction implements productInterface private $_bought = false ;
private $_sold = false ;
abstract public function doMore ();
public function doSell () /* the default implementation */
$this -> _sold = true ;
echo «defaultProductAbstraction doSell: < $this ->_sold > » . ¶ ;
>
public function doBuy () $this -> _bought = true ;
echo «defaultProductAbstraction doBuy: < $this ->_bought > » . ¶ ;
>
>
class defaultProductImplementation extends defaultProductAbstraction public function doMore () echo «defaultProductImplementation doMore()» . ¶ ;
>
>
class myProductImplementation extends defaultProductAbstraction public function doMore () echo «myProductImplementation doMore() does more!» . ¶ ;
>
public function doBuy () echo «myProductImplementation’s doBuy() and also my parent’s dubai()» . ¶ ;
parent :: doBuy ();
>
>
class myProduct extends defaultProductImplementation private $_bought = true ;
public function __construct () var_dump ( $this -> _bought );
>
public function doBuy () /* non-default doBuy implementation */
$this -> _bought = true ;
echo «myProduct overrides the defaultProductImplementation’s doBuy() here < $this ->_bought > » . ¶ ;
>
>
class myOtherProduct extends myProductImplementation public function doBuy () echo «myOtherProduct overrides myProductImplementations doBuy() here but still calls parent too» . ¶ ;
parent :: doBuy ();
>
>
echo «new myProduct()» . ¶ ;
$product = new myProduct ();
$product -> doBuy ();
$product -> doSell ();
$product -> doMore ();
echo ¶ . «new defaultProductImplementation()» . ¶ ;
$newProduct = new defaultProductImplementation ();
$newProduct -> doBuy ();
$newProduct -> doSell ();
$newProduct -> doMore ();
echo ¶ . «new myProductImplementation» . ¶ ;
$lastProduct = new myProductImplementation ();
$lastProduct -> doBuy ();
$lastProduct -> doSell ();
$lastProduct -> doMore ();
echo ¶ . «new myOtherProduct» . ¶ ;
$anotherNewProduct = new myOtherProduct ();
$anotherNewProduct -> doBuy ();
$anotherNewProduct -> doSell ();
$anotherNewProduct -> doMore ();
?>
Will result in:
/*
new myProduct()
bool(true)
myProduct overrides the defaultProductImplementation’s doBuy() here 1
defaultProductAbstraction doSell: 1
defaultProductImplementation doMore()
new defaultProductImplementation()
defaultProductAbstraction doBuy: 1
defaultProductAbstraction doSell: 1
defaultProductImplementation doMore()
new myProductImplementation
myProductImplementation’s doBuy() and also my parent’s dubai()
defaultProductAbstraction doBuy: 1
defaultProductAbstraction doSell: 1
myProductImplementation doMore() does more!
new myOtherProduct
myOtherProduct overrides myProductImplementations doBuy() here but still calls parent too
myProductImplementation’s doBuy() and also my parent’s dubai()
defaultProductAbstraction doBuy: 1
defaultProductAbstraction doSell: 1
myProductImplementation doMore() does more!
5 years ago
Also you may set return/arguments type declaring for abstract methods (PHP>=7.0)
declare( strict_types = 1 );
abstract class Adapter
protected $name ;
abstract public function getName (): string ;
abstract public function setName ( string $value );
>
class AdapterFoo extends Adapter
public function getName (): string
return $this -> name ;
>
// return type declaring not defined in abstract class, set here
public function setName ( string $value ): self
$this -> name = $value ;
return $this ;
>
>
?>
12 years ago
The documentation says: «It is not allowed to create an instance of a class that has been defined as abstract.». It only means you cannot initialize an object from an abstract class. Invoking static method of abstract class is still feasible. For example:
abstract class Foo
static function bar ()
echo «test\n» ;
>
>
5 years ago
Here is another thing about abstract class and interface.
Sometimes, we define an interface for a `Factory` and ease out some common methods of the `Factory` through an `abstract` class.
In this case, the abstract class implements the interface, but does not need to implement all methods of the interface.
The simple reason is, any class implementing an interface, needs to either implement all methods, or declare itself abstract.
Because of this, the following code is perfectly ok.
interface Element /**
* Constructor function. Must pass existing config, or leave as
* is for new element, where the default will be used instead.
*
* @param array $config Element configuration.
*/
public function __construct ( $config = [] );
/**
* Get the definition of the Element.
*
* @return array An array with ‘title’, ‘description’ and ‘type’
*/
public static function get_definition ();
/**
* Get Element config variable.
*
* @return array Associative array of Element Config.
*/
public function get_config ();
/**
* Set Element config variable.
*
* @param array $config New configuration variable.
*
* @return void
*/
public function set_config ( $config );
>
abstract class Base implements Element
/**
* Element configuration variable
*
* @var array
*/
protected $config = [];
/**
* Get Element config variable.
*
* @return array Associative array of Element Config.
*/
public function get_config () return $this -> config ;
>
/**
* Create an eForm Element instance
*
* @param array $config Element config.
*/
public function __construct ( $config = [] ) $this -> set_config ( $config );
>
>
class MyElement extends Base
public static function get_definition () return [
‘type’ => ‘MyElement’ ,
];
>
public function set_config ( $config ) // Do something here
$this -> config = $config ;
>
>
$element = new MyElement ( [
‘foo’ => ‘bar’ ,
] );
print_r ( $element -> get_config () );
?>
You can see the tests being executed here and PHP 5.4 upward, the output is consistent. https://3v4l.org/8NqqW
16 years ago
Ok. the docs are a bit vague when it comes to an abstract class extending another abstract class. An abstract class that extends another abstract class doesn’t need to define the abstract methods from the parent class. In other words, this causes an error:
abstract class class1 <
abstract public function someFunc ();
>
abstract class class2 extends class1 <
abstract public function someFunc ();
>
?>
Error: Fatal error: Can’t inherit abstract function class1::someFunc() (previously declared abstract in class2) in /home/sneakyimp/public/chump.php on line 7
However this does not:
abstract class class1 <
abstract public function someFunc ();
>
abstract class class2 extends class1 <
>
?>
An abstract class that extends an abstract class can pass the buck to its child classes when it comes to implementing the abstract methods of its parent abstract class.
6 years ago
An interface specifies what methods a class must implement, so that anything using that class that expects it to adhere to that interface will work.
eg: I expect any $database to have ->doQuery(), so any class I assign to the database interface should implement the databaseInterface interface which forces implementation of a doQuery method.
interface dbInterface public function doQuery ();
>
class myDB implements dbInterface public function doQuery () /* implementation details here */
>
>
$myDBObj = new myDB ()-> doQuery ();
?>
An abstract class is similar except that some methods can be predefined. Ones listed as abstract will have to be defined as if the abstract class were an interface.
eg. I expect my $person to be able to ->doWalk(), most people walk fine with two feet, but some people have to hop along 🙁
interface PersonInterface () /* every person should walk, or attempt to */
public function doWalk ( $place );
/* every person should be able to age */
public function doAge ();
>
abstract class AveragePerson implements PersonInterface () private $_age = 0 ;
public function doAge () $this -> _age = $this -> _age + 1 ;
>
public function doWalk ( $place ) echo «I am going to walk to $place » . PHP_EOL ;
>
/* every person talks differently! */
abstract function talk ( $say );
>
class Joe extends AveragePerson public function talk ( $say ) echo «In an Austrailian accent, Joe says: $say » . PHP_EOL ;
>
>
class Bob extends AveragePerson public function talk ( $say ) echo «In a Canadian accent, Bob says: $say » . PHP_EOL ;
>
public function doWalk ( $place ) echo «Bob only has one leg and has to hop to $place » . PHP_EOL ;
>
>
$people [] = new Bob ();
$people [] = new Joe ();
foreach ( $people as $person ) $person -> doWalk ( ‘over there’ );
$person -> talk ( ‘PHP rules’ );
>
?>
Разница между абстрактным классом и интерфейсом в PHP
Сравнение абстрактного класса и интерфейса в PHP. В чем разница между абстрактным классом и интерфейсом в PHP? Это один из самых распространненых вопросов на собеседованиях.
В этом уроке вы узнаете некоторые важные различия между абстрактным классом и интерфейсом.
Интерфейс в PHP
Интерфейс — это соглашение, контракт или договор. Когда класс реализует интерфейс, это означает, что он содержит публичные методы интерфейса и их реализации.
Когда мы создаем интерфейс в приложении, мы определяем контракт на то, что наш класс может делать, ничего не говоря о том, как этот класс будет это делать.
// Defined cacheInterface interface cacheInterface < public function get($key); public function set($key,$value); >/* * A Memcache class implements cacheInterface */ class Memcache implements cacheInterface < public function get($key)< // method body >public function set($key,$value) < // method body >>
В приведенном выше примере создается cacheInterface , содержащий публичные методы get() и set() . Любой класс, который реализует этот интерфейс, должен определить методы get() и set() .
В этом примере класс Memcache реализует cacheInterface . Это означает, что он придерживается контракта и определяет тело методов get() и set() . Аналогично, если какой-либо другой класс кэширования реализует этот интерфейс, он определит методы get() и set() .
Абстрактный класс в PHP
Абстрактный класс используется для определения базового каркаса или проекта дочерних классов. Класс, который расширяет абстрактный класс, должен определять некоторые или все его абстрактные методы.
Экземпляры абстрактных классов не могут быть созданы напрямую.
abstract class car < abstract public function modelType(); public function wheelCount() < echo "I have four wheels"; >> class HondaCity extends car < public function modelType()< echo "HondaCity"; >> $data = new HondaCity; $data->modelType(); $data->wheelCount();
Сравнение абстрактного класса и интерфейса в PHP
| Интерфейс | Абстрактный класс |
|---|---|
| Поддерживаем множественное наследование | Не поддерживаем множественное наследование |
| Не содержит data members | Может содержать data members |
| Не содержит конструктор | Может содержать конструктор |
| Содержит только объявление методов (сигнатуры методов) | Может содержать как сигнатуры методов так и их реализации |
| Не может иметь модификаторов доступа — все методы по умолчанию публичные | Может иметь модификаторы доступа |
| Методы не могут быть статическими | Только методы, содержащие реализацию, могут быть объявлены статическими |
1. Абстрактный класс действует как образец для классов, которые его наследуют. Дочерний класс, который наследует абстрактный класс, должен реализовывать методы, объявленые абстрактными в родительском классе. Абстрактный класс создается только для как элемент иерархии наследования. Это означает, что вы не можете создать объект абстрактного класса.
Интерфейс — это контракт. Он содержит только сигнатуры методов (без тела метода). Класс, который реализует интерфейс, должен реализовывать эти методы.
2. Класс может расширять только один абстрактный класс, тогда как класс может реализовывать несколько интерфейсов.
interface A <> interface B <> interface C <> //A class can implements multiple interfaces class Base implements A, B, C <>
3. В абстрактном классе мы можем определить переменные экземпляра и конкретные (неабстрактные) методы.
Но в интерфейсе все методы абстрактны. Мы не можем определить переменные экземпляра, но мы можем определить константы в интерфейсе.
4. Абстрактный класс хорош, когда есть некоторые общие черты, которые должны быть общими для всех объектов.
Используйте интерфейс, когда все функции должны быть реализованы по-разному для разных объектов. Все методы cacheInterface будут реализованы по-разному для всех классов.
Например — класс Memcache определяет тело метода get() и set() , но их реализация будет отличается от класса Redis.