- 接口没有构造函数,接口也可以有构造函数,抽象类可以有构造函数;
- 一个类可以同时实现多个接口,但一个类只能继承一个抽象类
- 接口中声明的方法只能是public的,默认也是public权限;抽象类可以是public、protected、private(只能非抽象方法可以是private)
- 抽象类使用extends继承抽象类(不可以使用extends继承接口!!), 接口可以使用implements 也可以使用extends继承一个或多个接口(implements是实现接口关键字)
- 接口中只能放抽象方法(没有abstract关键字修饰的)和const常量,抽象类中可以有成员属性变量、常量,已经实现的方法(非抽象方法)、抽象方法;(抽象方法没有方法体)
补充:有抽象方法的类一定是抽象类,但是抽象类不一定有抽象方法;可以同时继承抽象类和实现接口,extends要写在前面;接口也可以继承,通过使用 extends 操作符
接口解决了类不能多继承问题,接口适用于不同系列的类具有相同的动作,不是相同的系列,但具有相同的行为,这个就考虑使用接口,抽象类适用于同一系列,并且有需要继承的成员。
当你关注一个事物的本质的时候,用抽象类;当你关注一个操作的时候,用接口。
比如人和其他动物都会吃。把吃写成一个接口。因为一个类可以实现多个接口,所以还可以写喝接口等等。
人和学生,,学生具备人的特征和行为,把人写成抽象类,学生继承这个抽象类。(个人的理解)
下面的程序只是对上面的几点进行验证。划线部分是错的。
1 interface A 2 { 3 // public $a; //报错,不能有变量 4 const B = '2'; 5 public function __construct(); //可以有构造函数 6 public function foo(); 7 8 public function who(); 9 } 10 11 interface D 12 { 13 public function walk(); 14 } 15 16 interface E extends D,A //继承多个接口没报错 17 { 18 public function sing(); 19 } 20 21 // class F implements E 22 // { 23 // public function sing() { 24 // echo 'F implements E '; //报错,因为E继承多个接口,有5个抽象方法在这个例子中。需要全部实现。说明接口可以继承多个接口 25 // } 26 // } 27 28 // interface G implements A {} //报错,不能使用implements,implements是实现接口关键字 29 30 31 abstract class B implements A //不能用extends继承接口 32 { 33 public function foo() { 34 echo 222; 35 echo get_called_class(); 36 } 37 38 public function who() { 39 echo 333; 40 } 41 42 private function ime() { 43 echo '我自己的方法'; //非抽象方法可以设置为private 44 } 45 46 abstract protected function say(); //抽象方法不可以设置private 47 } 48 49 class C extends B implements A,D,E 50 { 51 public function __construct() { 52 echo 'this is construct'; 53 } 54 55 public function foo() { 56 echo 444; 57 // echo B; 58 parent::foo(); 59 } 60 61 public function who() { 62 echo 555; 63 } 64 65 public function say() { 66 echo 666; 67 } 68 69 public function walk() { 70 echo ' i can walk ---'; 71 } 72 73 public function sing() { 74 echo 'i can sing'; 75 } 76 } 77 78 $b = new C; 79 $b->foo(); 80 $b->walk(); 81 $b->sing();