一、 抽象类abstract class
1 .抽象类是指在 class 前加了 abstract 关键字且存在抽象方法(在类方法 function 关键字前加了 abstract 关键字)的类。
2 .抽象类不能被直接实例化。抽象类中只定义(或部分实现)子类需要的方法。子类可以通过继承抽象类并通过实现抽象类中的所有抽象方法,使抽象类具体化。
3 .如果子类需要实例化,前提是它实现了抽象类中的所有抽象方法。如果子类没有全部实现抽象类中的所有抽象方法,那么该子类也是一个抽象类,必须在 class 前面加上 abstract 关键字,并且不能被实例化。
代码如下:
abstract class A { /** 抽象类中可以定义变量 */ protected $value1 = 0; private $value2 = 1; public $value3 = 2; /** 也可以定义非抽象方法 */ public function my_print() { echo "hello,world/n"; } /** * 大多数情况下,抽象类至少含有一个抽象方法。抽象方法用abstract关键字声明,其中不能有具体内容。 * 可以像声明普通类方法那样声明抽象方法,但是要以分号而不是方法体结束。也就是说抽象方法在抽象类中不能被实现,也就是没有函数体“{some codes}”。 */ abstract protected function abstract_func1(); abstract protected function abstract_func2(); } abstract class B extends A { public function abstract_func1() { echo "implement the abstract_func1 in class A/n"; } /** 这么写在zend studio 8中会报错*/ //abstract protected function abstract_func2(); } class C extends B { public function abstract_func2() { echo "implement the abstract_func2 in class A/n"; } }
4 .如果像下面这样创建了一个继承自 A 的子类 B ,但是不实现抽象方法 abstract_func() :
代码如下:
Class B extends A{};
那么程序将出现以下错误:
代码如下:
Fatal error: Class B contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (A::abstract_func)
5 .如果 B 实现了抽象方法 abstract_func() ,那么 B 中 abstract_func() 方法的访问控制不能比 A 中 abstract_func() 的访问控制更严格,也就是说:
(1) 如果 A 中 abstract_func() 声明为 public ,那么 B 中 abstract_func() 的声明只能是 public ,不能是 protected 或 private
(2) 如果 A 中 abstract_func() 声明为 protected ,那么 B 中 abstract_func() 的声明可以是 public 或 protected ,但不能是 private
(3) 如果 A 中 abstract_func() 声明为 private ,嘿嘿,不能定义为 private 哦!( Fatal error : Abstract function A::abstract_func() cannot be declared private )
二、 接口interface
1 .抽象类提供了具体实现的标准,而接口则是纯粹的模版。接口只定义功能,而不包含实现的内容。接口用关键字 interface 来声明。
2 . interface 是完全抽象的,只能声明方法,而且只能声明 public 的方法,不能声明 private 及 protected 的方法,不能定义方法体,也不能声明实例变量 。然而, interface 却可以声明常量变量 。但将常量变量放在 interface 中违背了其作为接口的作用而存在的宗旨,也混淆了 interface 与类的不同价值。如果的确需要,可以将其放在相应的 abstract class 或 Class 中。
代码如下:
interface iA { const AVAR=3; public function iAfunc1(); public function iAfunc2(); } echo iA:: AVAR;
3 .任何实现接口的类都要实现接口中所定义的所有方法
代码如下:
class E implements iA { public function iAfunc1(){echo "in iAfunc1";} public function iAfunc2(){echo "in iAfunc2";} }
否则该类必须声明为 abstract 。
代码如下:
abstract class E implements iA{}
4 .一个类可以在声明中使用 implements 关键字来实现某个接口。这么做之后,实现接口的具体过程和继承一个仅包含抽象方法的抽象类是一样的。一个类可以同时继承一个父类和实现任意多个接口。 extends 子句应该在 implements 子句之前。 PHP 只支持继承自一个父类,因此 extends 关键字后只能跟一个类名。
代码如下:
interface iB { public function iBfunc1(); public function iBfunc2(); } class D extends A implements iA,iB { public function abstract_func1() { echo "implement the abstract_func1 in class A/n"; } public function abstract_func2() { echo "implement the abstract_func2 in class A/n"; } public function iAfunc1(){echo "in iAfunc1";} public function iAfunc2(){echo "in iAfunc2";} public function iBfunc1(){echo "in iBfunc1";} public function iBfunc2(){echo "in iBfunc2";} } class D extends B implements iA,iB { public function abstract_func1() { parent::abstract_func1(); echo "override the abstract_func1 in class A/n"; } public function abstract_func2() { echo "implement the abstract_func2 in class A/n"; } public function iAfunc1(){echo "in iAfunc1";} public function iAfunc2(){echo "in iAfunc2";} public function iBfunc1(){echo "in iBfunc1";} public function iBfunc2(){echo "in iBfunc2";} }
5 .接口不可以实现另一个接口,但可以继承多个
代码如下:
interface iC extends iA,iB{} class F implements iC { public function iAfunc1(){echo "in iAfunc1";} public function iAfunc2(){echo "in iAfunc2";} public function iBfunc1(){echo "in iBfunc1";} public function iBfunc2(){echo "in iBfunc2";} }
三、 抽象类和接口的异同
1. 相同点:
(1) 两者都是抽象类,都不能实例化。
(2) interface 实现类及 abstract class 的子类都必须要实现已经声明的抽象方法。
2. 不同点:
(1) interface 需要实现,要用 implements ,而 abstract class 需要继承,要用 extends 。
(2) 一个类可以实现多个 interface ,但一个类只能继承一个 abstract class 。
(3) interface 强调特定功能的实现,而 abstract class 强调所属关系。
(4) Obwohl sowohl Schnittstellenimplementierungsklassen als auch Unterklassen abstrakter Klassen entsprechende abstrakte Methoden implementieren müssen, sind die Implementierungsformen unterschiedlich. Jede Methode in der Schnittstelle ist eine abstrakte Methode, die nur deklariert wird (Deklaration, kein Methodenkörper) und von der Implementierungsklasse implementiert werden muss. Unterklassen einer abstrakten Klasse können selektiv implementiert werden. Diese Wahl hat zwei Auswirkungen: a) Nicht alle Methoden in der abstrakten Klasse sind abstrakt. Nur die Methoden mit abstrakter Klasse sind abstrakt und müssen von Unterklassen implementiert werden. Für diese Methoden ohne Zusammenfassung muss der Methodenkörper in der abstrakten Klasse definiert werden. b) Wenn eine Unterklasse der abstrakten Klasse ihn erbt, kann sie nicht-abstrakte Methoden direkt erben oder überschreiben, und für abstrakte Methoden kann sie wählen, ob sie implementiert werden sollen Die Implementierung kann ihren Unterklassen überlassen werden, diese Klasse muss jedoch auch als abstrakt deklariert werden. Da es sich um eine abstrakte Klasse handelt, kann sie natürlich nicht instanziiert werden.
(5) Die abstrakte Klasse ist der Vermittler zwischen Schnittstelle und Klasse. Die abstrakte Klasse spielt eine verbindende Rolle zwischen Schnittstelle und Klasse. Einerseits ist eine abstrakte Klasse abstrakt und kann abstrakte Methoden deklarieren, um die Funktionen zu standardisieren, die Unterklassen implementieren müssen. Andererseits kann sie Standardmethodenkörper für die direkte Verwendung oder Überschreibung durch Unterklassen definieren. Darüber hinaus kann es durch Vererbung auch eigene Instanzvariablen definieren, die von Unterklassen verwendet werden.
(6) Das abstrakte Schlüsselwort wird nicht verwendet und kann nicht vor der abstrakten Methode in der Schnittstelle hinzugefügt werden. Die implizite Standardmethode ist die abstrakte Methode, und das letzte Schlüsselwort kann nicht hinzugefügt werden, um die Vererbung abstrakter Methoden zu verhindern . Der abstrakten Methode in einer abstrakten Klasse muss „abstract“ vorangestellt werden, um anzuzeigen, dass sie explizit als abstrakte Methode deklariert ist.
(7) Die abstrakte Methode in der Schnittstelle ist standardmäßig öffentlich und kann nicht mit privaten oder geschützten Modifikatoren geändert werden. Abstrakte Methoden in abstrakten Klassen können mit public und protected geändert werden, jedoch nicht mit private.
3. Anwendungsfälle der Schnittstelle
(1) Klassen benötigen zur Koordination spezifische Schnittstellen, unabhängig davon, wie sie implementiert werden.
(2) existiert als Bezeichner, der eine bestimmte Funktion implementieren kann, oder es kann ein reiner Bezeichner ohne Schnittstellenmethoden sein.
(3) Es ist notwendig, eine Klassengruppe als eine einzelne Klasse zu behandeln, und der Anrufer kontaktiert diese Klassengruppe nur über die Schnittstelle.
(4) Es ist notwendig, mehrere spezifische Funktionen zu implementieren, und diese Funktionen haben möglicherweise überhaupt keine Verbindung.
4. Anwendungsfälle der abstrakten Klasse
Kurz gesagt, Sie können sie verwenden, wenn Sie sowohl eine einheitliche Schnittstelle als auch Instanzvariablen oder Standardmethoden benötigen. Die gebräuchlichsten sind:
(1) definiert eine Reihe von Schnittstellen, möchte aber nicht jede Implementierungsklasse zwingen, alle Schnittstellen zu implementieren. Sie können eine abstrakte Klasse verwenden, um eine Reihe von Methodenkörpern oder sogar leere Methodenkörper zu definieren, und dann kann die Unterklasse die Methoden auswählen, die sie abdecken möchte.
(2) In einigen Fällen können reine Schnittstellen allein die Koordination zwischen Klassen nicht erfüllen. Zur Unterscheidung verschiedener Beziehungen sind auch Variablen erforderlich, die Zustände in der Klasse darstellen. Die Vermittlerrolle des Abstracts kann hierfür gute Dienste leisten.
(3) Standardisiert eine Reihe gegenseitig koordinierter Methoden, von denen einige gemeinsam und zustandsunabhängig sind und gemeinsam genutzt werden können, ohne dass Unterklassen sie separat implementieren müssen, während andere Methoden erfordern, dass jede Unterklasse sie implementiert entsprechend dem eigenen spezifischen Zustand, um bestimmte Funktionen zu implementieren.
Das obige ist der detaillierte Inhalt vonDetaillierte Erläuterung der PHP-Schnittstelle und Beispielcode für die Verwendung abstrakter Klassen. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!