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 相关文章推荐
PHP在XP下IIS和Apache2服务器上的安装
Sep 05 PHP
获得Google PR值的PHP代码
Jan 28 PHP
php设计模式 Builder(建造者模式)
Jun 26 PHP
PHP中将网页导出为Word文档的代码
May 25 PHP
php图片的裁剪与缩放生成符合需求的缩略图
Jan 11 PHP
smarty缓存用法分析
Dec 16 PHP
修改PHP脚本使WordPress拦截垃圾评论的方法示例
Dec 10 PHP
CentOS下PHP7的编译安装及MySQL的支持和一些常见问题的解决办法
Dec 17 PHP
老生常谈文本文件和二进制文件的区别
Feb 27 PHP
PHP CodeIgniter分页实例及多条件查询解决方案(推荐)
May 20 PHP
laravel5.1框架model类查询的实现方法
Oct 08 PHP
laravel5环境隐藏index.php后缀(apache)的方法
Oct 12 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
弄了个检测传输的参数是否为数字的Function
2006/12/06 PHP
织梦模板标记简介
2007/03/11 PHP
php cookie 登录验证示例代码
2009/03/16 PHP
IE和Firefox在JavaScript应用中的兼容性探讨
2008/04/01 Javascript
JavaScript CSS修改学习第五章 给“上传”添加样式
2010/02/19 Javascript
javascript 面向对象 function类
2010/05/13 Javascript
函数式 JavaScript(一)简介
2014/07/07 Javascript
jQuery浏览器CSS3特写兼容实例
2015/01/19 Javascript
Jquery使用val方法读写value值
2015/05/18 Javascript
JavaScript基于ajax编辑信息用法实例
2015/07/15 Javascript
Bootstrap Paginator分页插件与ajax相结合实现动态无刷新分页效果
2016/05/27 Javascript
基于JavaScript实现鼠标向下滑动加载div的代码
2016/08/31 Javascript
Bootstrap 填充Json数据的实例代码
2017/01/11 Javascript
AngularJS中的作用域实例分析
2018/05/16 Javascript
详解基于Vue-cli搭建的项目如何和后台交互
2018/06/29 Javascript
webpack之引入图片的实现及问题
2018/10/08 Javascript
[50:15]VP vs Mineski 2018国际邀请赛淘汰赛BO3 第二场 8.22
2018/08/23 DOTA
python将多个文本文件合并为一个文本的代码(便于搜索)
2011/03/13 Python
为Python的Tornado框架配置使用Jinja2模板引擎的方法
2016/06/30 Python
Python 12306抢火车票脚本 Python京东抢手机脚本
2018/02/06 Python
python实现多线程网页下载器
2018/04/15 Python
python线程中同步锁详解
2018/04/27 Python
python把数组中的数字每行打印3个并保存在文档中的方法
2018/07/17 Python
python web框架Flask实现图形验证码及验证码的动态刷新实例
2019/10/14 Python
pytorch中的自定义反向传播,求导实例
2020/01/06 Python
python如何写出表白程序
2020/06/01 Python
python 实现aes256加密
2020/11/27 Python
女士和男士时尚鞋在线购物:Shoespie
2019/02/28 全球购物
公务员年总结的自我评价
2013/10/25 职场文书
实习鉴定范文
2013/12/19 职场文书
大学生职业生涯设计书
2014/01/02 职场文书
安全生产工作汇报
2014/10/28 职场文书
考试作弊检讨书范文
2015/01/27 职场文书
铁人纪念馆观后感
2015/06/16 职场文书
网吧温馨提示
2015/07/17 职场文书
Nginx使用ngx_http_upstream_module实现负载均衡功能示例
2022/08/05 Servers