PHP之预定义接口详解


Posted in PHP onJuly 29, 2015

在PHP中有好几个预定义的接口,比较常用的四个接口(IteratorAggregate(聚合式aggregate迭代器Iterator)CountableArrayAccessIterator)分别给大家详细介绍下。

IteratorAggregate(聚合式aggregate迭代器Iterator)接口

IteratorAggregate extends Traversable {

 abstract public Traversable getIterator(void)

}

这个接口实现了一个功能——创建外部迭代器,具体怎么理解呢,当我们使用foreach对对象进行便遍历的时候,如果没有继承IteratorAggregate接口,遍历的是对象中所有的public属性(只能是public $var这种形式)。要是继承了IteratorAggregate,会使用类中实现的getIterator方法返回的对象,这里要注意返回的一定要是一个Traversable对象或者扩展自Traversable的对象,否则会抛出异常

 

//看个例子
class My{
 private $_data = [
 'a' => '燕睿涛',
 'b' => 'yanruitao',
 'c' => 'LULU',
 ];
 
 public function getIterator()
 {
 return new ArrayIterator($this->_data);
 }
}
$obj = new My;
foreach ($obj as $key => $value) {
 echo "$key => $value\n";
}
//输出结果为空 

class My implements IteratorAggregate {
 private $_data = [
 'a' => '燕睿涛',
 'b' => 'yanruitao',
 'c' => 'LULU',
 ];

 public function getIterator()
 {
 return new ArrayIterator($this->_data);
 }
}
$obj = new My;
foreach ($obj as $key => $value) {
 echo "$key => $value\n";
}
//结果:
a => 燕睿涛
b => yanruitao
c => LULU

Countable接口

Countable {

 abstract public int count(void)

}

这个接口用于统计对象的数量,具体怎么理解呢,当我们对一个对象调用count的时候,如果函数没有继承Countable将一直返回1,如果继承了Countable会返回所实现的count方法所返回的数字,看看下面的例子:

class CountMe
{ 
 protected $_myCount = 3; 

 public function count() 
 { 
 return $this->_myCount; 
 } 
} 

$countable = new CountMe(); 
echo count($countable);
//返回1

class CountMe implements Countable
{ 
 protected $_myCount = 3; 

 public function count() 
 { 
 return $this->_myCount; 
 } 
} 

$countable = new CountMe(); 
echo count($countable); 
//返回3


ArrayAccess接口
ArrayAccess {
 abstract public boolean offsetExists(mixed $offset)
 abstract public mixed offsetGet(mixed $offset)
 public void offsetSet(mixed $offset, mixed $value)
 public void offsetUnset(mixed $offset)
}


class CountMe
{ 
 protected $_myCount = 3; 

 public function count() 
 { 
  return $this->_myCount; 
 } 
} 

$countable = new CountMe(); 
echo count($countable);
//返回1

class CountMe implements Countable
{ 
 protected $_myCount = 3; 

 public function count() 
 { 
  return $this->_myCount; 
 } 
} 

$countable = new CountMe(); 
echo count($countable); 
//返回3

ArrayAccess接口

ArrayAccess {

 abstract public boolean offsetExists(mixed $offset)

    abstract public mixed offsetGet(mixed $offset)

    public void offsetSet(mixed $offset, mixed $value)

    public void offsetUnset(mixed $offset)

}

这个接口的作用是让我们可以像访问数组一样访问对象,这个怎么说好呢,我猜其实就是php在词法分析的时候如果碰到了数组的方式使用对象,就回去对象中查找是否有实现ArrayAccess如果有的话,进行对应的操作(set、unset、isset、get),这样我们就可以在类里面放置一个array,让类实现数组方式的基本操作,下面看个例子:

class myObj
{
 
}
$obj = new myObj;
$obj['name'];
//Fatal error: Cannot use object of type myObj as array in 

class myObj implements ArrayAccess 
{
 public function offsetSet($offset, $value)
 {
  echo "offsetSet : {$offset} => {$value}\n";
 }

 public function offsetExists($offset)
 {
  echo "offsetExists : {$offset}\n";
 }

 public function offsetUnset($offset)
 {
  echo "offsetUnset : {$offset}\n";
 }

 public function offsetGet($offset)
 {
  echo "offsetGet : {$offset}\n";
 }
}
$obj = new myObj;
$obj[1] = '燕睿涛';
isset($obj['name']);
unset($obj['name']);
$obj['yrt'];

//输出结果:
offsetSet : 1 => 燕睿涛
offsetExists : name
offsetUnset : name
offsetGet : yrt

class myObj implements ArrayAccess 
{
 private $_data = [];
 public function offsetSet($offset, $value)
 {
  $this->_data[$offset] = $value;
 }

 public function offsetExists($offset)
 {
  return isset($this->_data[$offset]);
 }

 public function offsetUnset($offset)
 {
  unset($this->_data[$offset]);
 }

 public function offsetGet($offset)
 {
  return $this->_data[$offset];
 }
}

$obj = new myObj;
$obj['yrt'] = '燕睿涛';
var_dump($obj['yrt']);
var_dump(isset($obj['yrt']));
unset($obj['yrt']);
var_dump(isset($obj['yrt']));
var_dump($obj['yrt']);

//输出:
string(9) "燕睿涛"
bool(true)
bool(false)
Notice: Undefined index: yrt //最后一个会报出Notice

上面的对象只能是基本的数组操作,连遍历都不行,结合之前的IteratorAggregate可以进行foreach:

class myObj implements ArrayAccess, IteratorAggregate
{
private $_data = [];

 public function getIterator()
 {
  return new ArrayIterator($this->_data);
 }

 ......
}
$obj = new myObj;
$obj['yrt'] = '燕睿涛';
$obj[1] = '燕睿涛';
$obj['name'] = '燕睿涛';
$obj['age'] = 23;

foreach ($obj as $key => $value) {
 echo "{$key} => {$value}\n";
}
//输出:
yrt => 燕睿涛
1 => 燕睿涛
name => 燕睿涛
age => 23

Iterator接口:

Iterator extends Traversable {

    abstract public mixed current(void)

    abstract public scalar key(void)

    abstract public void next(void)

    abstract public void rewind(void)

    abstract public boolean valid(void)

}

可在内部迭代自己的外部迭代器或类的接口,这是官方文档给出的解释,看着还是不好理解,其实我感觉这个接口实现的功能和trratorAggregate(文档:创建外部迭代器接口,接口直接返回一个迭代器)类似,不过这个在类的定义里面自己实现了,看个例子:

class myObj implements Iterator{

 private $_data = [];

 public function __construct(Array $arr)
 {
 $this->_data = $arr;
 }

 public function current()
 {
 return current($this->_data);
 }

 public function key()
 {
 return key($this->_data);
 }

 public function next()
 {
 next($this->_data);
 }

 public function rewind()
 {
 reset($this->_data);
 }

 public function valid()
 {
 return $this->key() !== NULL;
 }
}

$t = [
 'yrt' => '燕睿涛',
 'name' => '燕睿涛',
 false,
 '燕睿涛'
];
$obj = new myObj($t);

foreach ($obj as $key => $value) {
 echo "{$key} => ".var_export($value, true)."\n";
}
//输出:
yrt => '燕睿涛'
name => '燕睿涛'
0 => false
1 => '燕睿涛'

上面这个参考了鸟哥的一篇文章关于一笔试题(Iterator模式),不过鸟哥的那个判断valid有点瑕疵,当碰到值北来就是false的时候就会截断

总结
说了这么多好像还是没有体会到他们的用处,建议看看Yii2的源码,源码里面大量使用了这些东西,看了之后,你会慢慢觉得“哦~好像还真是挺有用的。。。。”

以上就是本文全部介绍,希望大家喜欢。

PHP 相关文章推荐
一个ORACLE分页程序,挺实用的.
Oct 09 PHP
第十四节--命名空间
Nov 16 PHP
一些PHP Coding Tips(php小技巧)[2011/04/02最后更新]
May 02 PHP
php header功能的使用
Oct 28 PHP
带密匙的php加密解密示例分享
Jan 29 PHP
一个PHP实现的轻量级简单爬虫
Jul 08 PHP
PHP中文竖排转换实现方法
Oct 23 PHP
学习php设计模式 php实现合成模式(composite)
Dec 08 PHP
PHP统计目录中文件以及目录中目录大小的方法
Jan 09 PHP
php实现的XML操作(读取)封装类完整实例
Feb 23 PHP
PHP实现将优酷土豆腾讯视频html地址转换成flash swf地址的方法
Aug 04 PHP
Laravel框架控制器的middleware中间件用法分析
Sep 30 PHP
PHP实现的迷你漂流瓶
Jul 29 #PHP
PHP之浮点数计算比较以及取整数不准确的解决办法
Jul 29 #PHP
PHP实现简单搜歌的方法
Jul 28 #PHP
PHP读取配置文件类实例(可读取ini,yaml,xml等)
Jul 28 #PHP
PHP实现简单的新闻发布系统实例
Jul 28 #PHP
PHP实现的memcache环形队列类实例
Jul 28 #PHP
如何实现php图片等比例缩放
Jul 28 #PHP
You might like
PHP将DateTime对象转化为友好时间显示的实现代码
2011/09/20 PHP
php接口与接口引用的深入解析
2013/08/09 PHP
PHP 面向对象程序设计(oop)学习笔记 (四) - 异常处理类Exception
2014/06/12 PHP
Symfony2学习笔记之插件格式分析
2016/03/17 PHP
wordpress网站转移到本地运行测试的方法
2017/03/15 PHP
javascript中的undefined 与 null 的区别  补充篇
2010/03/17 Javascript
javascript对数组的常用操作代码 数组方法总汇
2011/01/27 Javascript
javascript使用中为什么10..toString()正常而10.toString()出错呢
2013/01/11 Javascript
jQuery数据缓存功能的实现思路及简单模拟
2013/05/27 Javascript
js 实现 input type="file" 文件上传示例代码
2013/08/07 Javascript
Knockout visible绑定使用方法
2013/11/15 Javascript
nodeType属性返回被选节点的节点类型介绍
2013/11/22 Javascript
JS判断客服QQ号在线还是离线状态的方法
2015/01/13 Javascript
jQuery的end()方法使用详解
2015/07/15 Javascript
Vue.js每天必学之组件与组件间的通信
2016/09/08 Javascript
微信小程序 教程之wxapp 视图容器 view
2016/10/19 Javascript
微信小程序 picker-view 组件详解及简单实例
2017/01/10 Javascript
bootstrap 模态框(modal)实现水平垂直居中显示
2017/01/23 Javascript
浅谈Node.js轻量级Web框架Express4.x使用指南
2017/05/03 Javascript
详解angularjs利用ui-route异步加载组件
2017/05/21 Javascript
SpringMVC+bootstrap table实例详解
2017/06/02 Javascript
使用mint-ui开发项目的一些心得(分享)
2017/09/07 Javascript
常用的 JS 排序算法 整理版
2018/04/05 Javascript
JavaScript字符串转数字的5种方法及遇到的坑
2018/07/16 Javascript
Angular resolve基础用法详解
2018/10/03 Javascript
Python实现字典去除重复的方法示例
2017/07/31 Python
Python 通过打码平台实现验证码的实现
2019/05/13 Python
HQhair美国/加拿大:英国化妆品、美容及美发产品商城
2019/04/15 全球购物
函授本科自我鉴定
2013/11/03 职场文书
法律进社区实施方案
2014/03/21 职场文书
导师推荐信范文
2014/05/09 职场文书
假面舞会策划方案
2014/05/29 职场文书
质量管理标语
2014/06/12 职场文书
2015年街道除四害工作总结
2015/05/15 职场文书
创业计划书之酒店
2019/08/30 职场文书
分享几个JavaScript运算符的使用技巧
2021/04/24 Javascript