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
Dec 14 PHP
在PHP中使用模板的方法
May 24 PHP
在PHP中使用curl_init函数的说明
Nov 02 PHP
PHP设计模式之迭代器模式的深入解析
Jun 13 PHP
PHP中source #N问题的解决方法
Jan 27 PHP
PHP对表单提交特殊字符的过滤和处理方法汇总
Feb 18 PHP
如何使用GDB调试PHP程序
Dec 08 PHP
PHP中使用foreach()遍历二维数组的简单实例
Jun 13 PHP
ThinkPHP5框架缓存查询操作分析
May 30 PHP
Laravel实现通过blade模板引擎渲染视图
Oct 25 PHP
php实现将数组或对象写入到文件的方法小结【三种方法】
Apr 22 PHP
通过PHP实现获取访问用户IP
May 09 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
SONY ICF-F10中波修复记
2021/03/02 无线电
PHP实现导出带样式的Excel
2016/08/28 PHP
PHP页面输出搜索后跳转下一页的处理方法
2016/09/30 PHP
PHP实现的mongoDB数据库操作类完整实例
2018/04/10 PHP
laravel框架中视图的基本使用方法分析
2019/11/23 PHP
php实现的简单多进程服务器类完整示例
2020/02/01 PHP
jQuery 动画基础教程
2008/12/25 Javascript
JavaScript表单通过正则表达式验证电话号码
2014/03/14 Javascript
clipboard.js无需Flash无需依赖任何JS库实现文本复制与剪切
2015/10/10 Javascript
javascript数据类型验证方法
2015/12/31 Javascript
学习JavaScript设计模式之享元模式
2016/01/18 Javascript
Angular2表单自定义验证器的实现
2016/10/19 Javascript
关于angularJs指令的Scope(作用域)介绍
2016/10/25 Javascript
Vue服务端渲染和Vue浏览器端渲染的性能对比(实例PK )
2017/03/31 Javascript
vue不通过路由直接获取url中参数的方法示例
2017/08/24 Javascript
Vuex 快速入门(简单易懂)
2018/09/20 Javascript
vue-router命名路由和编程式路由传参讲解
2019/01/19 Javascript
node微信开发之获取access_token+自定义菜单
2019/03/17 Javascript
vue集成kindeditor富文本的实现示例代码
2019/06/07 Javascript
vue中实现上传文件给后台实例详解
2019/08/22 Javascript
使用Vue-cli3.0创建的项目 如何发布npm包
2019/10/10 Javascript
vue 监听窗口变化对页面部分元素重新渲染操作
2020/07/28 Javascript
python读取浮点数和读取文本文件示例
2014/05/06 Python
Python变量和数据类型详解
2017/02/15 Python
Python 分发包中添加额外文件的方法
2019/08/16 Python
Python实现线性插值和三次样条插值的示例代码
2019/11/13 Python
Python namedtuple命名元组实现过程解析
2020/01/08 Python
Python3 读取Word文件方式
2020/02/13 Python
python GUI库图形界面开发之PyQt5简单绘图板实例与代码分析
2020/03/08 Python
使用Python对Dicom文件进行读取与写入的实现
2020/04/20 Python
Python3爬虫中Splash的知识总结
2020/07/10 Python
python中spy++的使用超详细教程
2021/01/29 Python
html5使用Canvas绘图的使用方法
2017/11/21 HTML / CSS
HTML5单页面手势滑屏切换原理
2016/03/21 HTML / CSS
2015年八一建军节慰问信
2015/03/23 职场文书
复兴之路展览观后感
2015/06/02 职场文书