抽象类

抽象类不能被直接实例化。抽象类只定义(或部分实现)子类需要的方法。子类可以继承它并且通过实现其中的抽象方法,使抽象类具体化。你可以用abstract关键字定义一个抽象类。大多数情况下,抽象类至少包含一个抽象方法。抽象方法用abstract关键字声明,其中不能有具体内容。

abstract class ShopProductWriter{
    protected $products = array();   
     public function addProduct(ShopProduct $shopProduct)
    {
        $this->products[] = $shopProduct;
    }    abstract public function write();}
登录后复制

创建抽象方法后,要确保所有的子类中都实现了该方法,但实现的细节可以先不确定。每个子类都必须实现抽象类中的所有抽象方法,或者把它们自身也声明为抽象方法。扩展类不仅仅负责简单实现抽象类中的方法,还必须重新声明方法。新的实现方法的访问控制不能比抽象方法的访问控制更严格。新的实现方法的参数个数应该和抽象方法的参数个数一样,重新生成对应的类型提示。

class XmlProductWriter extends ShopProductWriter{

    public function write()
    {
        $str='<?xml version="1.0" encoding="UTF-8"?>'."\n";        
        $str.="<products>\n";        
        foreach ($this->products as $shopProduct) {            
        $str.="\t<product title=\"{$shopProduct->getTitle()}\">\n";            
        $str.="\t\t<summary>\n";            
        $str.="\t\t{$shopProduct->getSummaryLine()}\n";            
        $str.="\t\t</summary>\n";            
        $str.="\t</product>\n";
        }        
        $str.="</products>\n";        
        print $str;
    }
}class TextProductWriter extends ShopProductWriter{

    public function write()
    {
        $str="PRODUCTS:\n";        
        foreach ($this->products as $shopProduct) {            
        $str.=$shopProduct->getSummaryLine()."\n";
        }        
        print $str;
    }
}
登录后复制

接口

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

interface Chargeable{
    public function getPrice();}
登录后复制

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

class ShopProduct implements Chargeable
{
    //...
    function getPrice()
    {        return ($this->getPrice-$this->discount);
    }
    //...}
登录后复制

ShopProduct类已经有一个getPrice()方法,那么实现Chargeable接口还有用吗?答案是肯定的,因为类型。实现接口的类接受了它继承的类及实现的接口的类型。

任何类都可以实现接口,接口可以有效地将不相关的类型联结起来。一个类可以同时继承一个父类和实现任意个接口。extends子句一个在implements子句之前。

class Consultancy extends TimedService implements Bookable, Chargeable{//...}
登录后复制

延迟静态绑定:static关键字

该特性最明显的标志就是新关键字static。static类似于self,但它指的是被调用的类而不是包含类。在本例中,它的意思是调用Document::create()将生成一个新的Document对象,而不是试图实例化一个DomainObject对象。

abstract class DomainObject{

    public static function create()
    {
        return new static();
    }
}class User extends DomainObject{   }class Document extends DomainObject{}

print_r(Document::create());//输出为Document Object//      (//      )
登录后复制

static关键字不仅仅可以用于实例化。和self和parent一样,static还可以作为静态方法调用的标识符,甚至是从非静态上下文中调用。

abstract class DomainObject{
    private $group;    public function construct()
    {
        $this->group=static::getGroup();
    }    public static function create()
    {
        return new static();
    }    static function getGroup(){
        return "default";
    }
}class User extends DomainObject{   }class Document extends DomainObject{
    static function getGroup(){
        return "document";
    }
}class SpreadSheet extends Document{}

print_r(User::create());
print_r(SpreadSheet::create());//输出为User Object//      
(//          
[group:DomainObject:private]=>default
//      
)//      
SpreadSheet Object//      
(//          
[group:DomainObject:private]=>document//      
)
登录后复制

以上就是深入了解PHP面向对象、模式与实践-高级特性(二)的详细内容,更多请关注Work网其它相关文章!

09-17 10:30