PHP之抽象类与接口

       引入抽象类是PHP 5的一个重要变化。抽象类不能被直接实例化,抽象类中只定义(或部分实现)子类需要的方法。子类可以继承它并通过实现其中的抽象方法,使抽象类具体化。关键字abstract 定义一个抽象类。

      大多数情况下,抽象类至少包含一个抽象方法。抽象方法用abstract关键字声明,其中不能有具体内容。可以像声明普通类方法那样声明抽象方法,但要以分号而不是方法体结束。

 1 <?php
 2 abstract class Simple
 3 {
 4       protected $arr = array(); 
 5 
 6       public function say()
 7       {
 8             echo "hello";
 9       }
10       
11       abstract public function write();
12 }
13 
14 class Writer extends simple
15 {
16       public function write()
17      {
18           // .....具体实现
19      }
20 }
21 ?>

      在PHP 4中,我们可以用包含警告或die()语句模拟抽象类。

1 <?php
2 class AbstractClass
3 {
4       function abstractFunction()
5       {
6            die("AbstractClass::abstractFunction() is abstract\n");
7       }
8 }
9 ?>

     这里存在一个问题,就是这个基类的抽象性只有在抽象方法调用时(即代码运行时)才能检测。在PHP 5中,抽象类在被解析时就被检测,所以更加安全。

接口

     抽象类提供了具体的实现标准,而接口则是纯粹的模版。接口只能定义功能,而不包括实现的内容。接口可用关键字interface来声明。接口可以包含属性和方法的声明,但是方法体为空。

     定义一个接口:

1 <?php
2 interface InterClass
3 {
4       public functon example();  
5 }
6 ?>

     任何实现接口的类都要实现接口中所定义的所有方法,否则该类必须声明为abstract。一个类可以在声明中使用implements关键字来实现某个接口。

     一个类可以同时继承一个父类和实现任意个接口。extends字句应该放在implements字句之前:

<?php
class Consultancy extends TimedService implements Bookable, Chargeable
{
       //...
}

?>

     PHP只支持继承自一个父类,因此extends关键字只能在一个类名之前。

延迟静态绑定:static 关键字

     学习了抽象类和接口请看下面的代码:

 1 <?php
 2 abstract class DomainObject
 3 {}
 4 
 5 class User extends DomainObject
 6 {
 7        public static function create()
 8        {
 9              return new User();
10        }
11 }
12 
13 class Document extends DomainObject
14 {
15        public static function create()
16        {
17              return new Document();
18        }
19 }
20 ?>

      发现在创建这两个类的时候,存在代码重复,如果将重复代码提取到基类呢?

 1  <?php
 2   abstract class DomainObject
 3   {
 4        public static function create()
 5        {
 6            return new self();
 7        }
 8   }
 9  
10   class User extends DomainObject
11  {
12  }
13  
14  class Document extends DomainObject
15  {
16  }
17 
18   Document :: create();
19 ?>

       可以运行下结果,报错了。。。

       实际上,self对该类所起的作用与$this对对象所起的作用并不完全相同。self指的不是调用的上下文,它指的是解析上下文,因此,如果运行则报错。

       在PHP 5.3中引入了延迟静态绑定的概念。该特性最明显的标志就是新关键字static。static类似于self,但它指的是表调用的类而不是包含类。

 1 <?php
 2    abstract class DomainObject
 3    {
 4         public static function create()
 5         {
 6             return new  static();
 7         }
 8    }
 9   
10    class User extends DomainObject
11   {
12   }
13   
14   class Document extends DomainObject
15   {
16   }
17  
18    var_dump(Document :: create());
19  ?>

       现在运行则通过。static不仅可以用于实例化。和self和parent一样,static还可以作为静态方法调用的标示符,甚至从非静态上下文中调用。

 1 <?php
 2 abstract class DomainObject
 3 {
 4     private $group;
 5 
 6     public function __construct()
 7     {
 8         $this->group = static::getGroup();
 9     }
10 
11     public static function create()
12     {
13         return new static();
14     }
15 
16     static function getGroup()
17     {
18         return 'Default';
19     }
20 }
21 
22 class User extends DomainObject
23 {
24 }
25 
26 class Document extends DomainObject
27 {
28     static function getGroup()
29     {
30         return "document";
31     }
32 }
33 
34 class SpreadSheet extends Document
35 {
36 }
37 
38 print_r(User::create());
39 print_r(SpreadSheet::create());
40  ?>

       运行看结果,PHP5.3之前self只能查找DomainObject类中的getGroup()。

<<因果&矛盾>>
原文地址:https://www.cnblogs.com/bridger/p/2715055.html