您的位置 首页 php

PHP 新特性:如何善用接口与Trait

文章内容

接口不是新特性但是很重要,接口是两个php对象的契约。其目的不是让一个对象依赖另一个对象的身份,而是依赖另一个对象的能力。接口把我们的代码和依赖解耦,而且允许我们的代码依赖任何实现了预期接口的第三方代码。我们不关心第三方代码如何实现接口,只去关心他有没有去实现接口。

如果我们写的类去处理特定的对象, 那么类的功能就被限定了,只能处理那个类。但是我们的对象如果是处理的接口,那么代码立即就能知道如何处理实现这一接口的任何对象,我们的代码不管接口如何实现只需要关心有没有实现。

文档处理类实现

<?phpclass DocumentStore {  protected  $data = []; /** * 参数限定为 Documentable 对象,这是一个接口 */ public function addDocument(Documentable $document) { $key = $document->getId(); $value = $document->getContent(); $this->data[$key] = $value; } public function getDocuments() { return $this->data; }} 

这个是我们的文档处理类,它面向的是接口操作 Documentable 实现:

<?phpinterface Documentable { public function getId(); public function getContent();} 

具体实现接口的类,比如是从html获得的文档 实现:

<?phpclass HtmlDocument implements Documentable { protected $url; public function __construct($url) { $this->url = $url; } public function getId() { return $this->url; } public function getContent() { $ ch  = curl_init(); curl_setopt($ch, CURLOPT_URL, $this->url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 3); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); curl_setopt($ch, CURLOPT_MAXREDIRS, 3); $html = curl_exec($ch); curl_close($ch); return $html; }} 

读取流数据的文档 实现:

<?phpclass StreamDocument implements Documentable { protected $resource; protected $buffer; public function __construct($resource, $buffer = 4096) { $this->resource = $resource; $this->buffer = $buffer; } public function getId() { return 'resource-' . (int)$this->resource; } public function getContent() { $streamContent = ''; rewind($this->resource); while (feof($this->resource) === false) { $streamContent .= fread($this->resource, $this->buffer); } return $streamContent; }} 

具体使用 :

<?phprequire 'Documentable.php';require 'DocumentStore.php';require 'HtmlDocument.php';require 'StreamDocument.php';require 'CommandOutputDocument.php';$documentStore = new DocumentStore();// Add HTML document$htmlDoc = new HtmlDocument('$documentStore->addDocument($htmlDoc);// Add stream document$streamDoc = new StreamDocument(fopen('stream.txt', 'rb'));$documentStore->addDocument($streamDoc);// Add terminal command document$cmdDoc = new CommandOutputDocument('cat /etc/hosts');$documentStore->addDocument($cmdDoc);print_r($documentStore->getDocuments()); 

需要说明的是参数类型 addDocument 参数类型限定为 Documentable 实现该接口的对象都可以做参数。

性状( trait )

性状是类的部分实现,可以混入一个或者多个现有的类实现中,有两个作用:

1表明类可以做什么;

2 提供模块化实现;

使用场景:

我们做面向对象的开发的时候都会通过基类实现基本功能,完后子类具体实现详细的功能,各类之间有明显的自然的继承关系,如果有一个逻辑既不属于A类也不属于B类,那么在性状出现之前我们怎么解决:

解决办法一:做一个父类 让A, B都继承,这样做的缺点是,强制把两个不相关的类继承同一父类,结构混乱破坏了封装。

解决方法二:做一个接口,让A, B都去实现这个接口,强于上一个方法,但是缺点是相同的逻辑会在多个类中实现,代码逻辑冗余,加大维护成本。

解决办法三:使用性状(trait)推荐做法。

定义性状:

<?php// 推荐把性状当类看待,一个文件定义一个性状trait MyTrait { protected $p1; public $p2; public function f1() { }} 

使用性状:

<?phpclass MyClass { use MyTrait;} 

之后实例对象就可以使用性状里的属性方法就像使用本类的一样;php解释器会把性状的代码复制到类定义中,有点像c语言中的宏。

b918cee72c7a44e7b0aef9bca8b9b853

文章来源:智云一二三科技

文章标题:PHP 新特性:如何善用接口与Trait

文章地址:https://www.zhihuclub.com/31131.shtml

关于作者: 智云科技

热门文章

网站地图