您的位置:首页 > 编程语言 > PHP开发

深入PHP面向对象、模式与实践——高级特性(2)

2017-03-18 16:59 821 查看

抽象类

抽象类不能被直接实例化。抽象类只定义(或部分实现)子类需要的方法。子类可以继承它并且通过实现其中的抽象方法,使抽象类具体化。你可以用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还可以作为静态方法调用的标识符,甚至是从非静态上下文中调用
4000


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