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的历史和优缺点
Oct 09 PHP
php adodb操作mysql数据库
Mar 19 PHP
php session 错误
May 21 PHP
一个PHP验证码类代码分享(已封装成类)
Jul 17 PHP
PHP图片验证码制作实现分享(全)
May 10 PHP
php Ubb代码编辑器函数代码
Jul 05 PHP
Yii操作数据库的3种方法
Mar 11 PHP
PHP 实现代码复用的一个方法 traits新特性
Feb 22 PHP
从wamp到xampp的升级之路
Apr 08 PHP
php图像处理类实例
Jul 28 PHP
PHP使用GD库输出汉字的方法【测试可用】
Nov 10 PHP
实例讲解PHP页面静态化
Feb 05 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文章内容分页并生成相应的htm静态页面代码
2010/06/07 PHP
PHP实现指定字段的多维数组排序函数分享
2015/03/09 PHP
获取JavaScript用户自定义类的类名称的代码
2007/03/08 Javascript
异步加载script的代码
2011/01/12 Javascript
日期处理的js库(迷你版)--自建js库总结
2011/11/21 Javascript
js清除input中type等于file的值域(示例代码)
2013/12/24 Javascript
IE、FF浏览器下修改标签透明度
2014/01/28 Javascript
一个Action如何调用两个不同的方法
2014/05/22 Javascript
node.js express安装及示例网站搭建方法(分享)
2016/08/22 Javascript
AngularJs ng-repeat 嵌套如何获取外层$index
2016/09/21 Javascript
详解vue嵌套路由-params传递参数
2017/05/23 Javascript
浅谈JsonObject中的key-value数据解析排序问题
2017/12/06 Javascript
JS中使用textPath实现线条上的文字
2017/12/25 Javascript
AjaxFileUpload.js实现异步上传文件功能
2019/04/19 Javascript
微信小程序使用canvas自适应屏幕画海报并保存图片功能
2019/07/25 Javascript
Vue使用vue-draggable 插件在不同列表之间拖拽功能
2020/03/12 Javascript
微信小程序实现购物车功能
2020/11/18 Javascript
[01:12:27]EG vs Secret 2018国际邀请赛淘汰赛BO3 第二场 8.22
2018/08/23 DOTA
python使用clear方法清除字典内全部数据实例
2015/07/11 Python
Pandas之drop_duplicates:去除重复项方法
2018/04/18 Python
实例分析python3实现并发访问水平切分表
2018/09/29 Python
详解python3 + Scrapy爬虫学习之创建项目
2019/04/12 Python
python django生成迁移文件的实例
2019/08/31 Python
python对指定字符串逆序的6种方法(小结)
2020/04/02 Python
国际知名军事风格休闲装品牌:Alpha Industries(阿尔法工业)
2017/05/24 全球购物
世界上第一个创建了罩杯系统的美国内衣品牌:Maidenform
2019/03/23 全球购物
俄罗斯韩国化妆品网上商店:Cosmasi.ru
2019/10/31 全球购物
加拿大专业美发产品购物网站:Chatters
2021/02/28 全球购物
创业计划书撰写原则
2014/01/25 职场文书
员工拓展培训方案
2014/02/15 职场文书
2014年路政工作总结
2014/12/10 职场文书
推荐信范文大全
2015/03/27 职场文书
2015年乡镇纪检工作总结
2015/04/22 职场文书
用python批量解压带密码的压缩包
2021/05/31 Python
java如何实现socket连接方法封装
2021/09/25 Java/Android
面试中老生常谈的MySQL问答集锦夯实基础
2022/03/13 MySQL