PHP Predefined Interfaces 预定义接口

SPL提供了6个迭代器接口:

Traversable

遍历接口(检测一个类是否可以使用 foreach 进行遍历的接口)

Iterator

迭代器接口(可在内部迭代自己的外部迭代器或类的接口)

IteratorAggregate

聚合式迭代器接口(创建外部迭代器的接口)

OuterIterator

迭代器嵌套接口(将一个或多个迭代器包裹在另一个迭代器中)

RecursiveIterator

递归迭代访问接口(提供递归访问功能)

SeekableIterator

可索引迭代访问接口(实现查找功能)

下面对各种迭代器接口简单介绍一下:

1. Traversable

Traversable接口实际上不是一个接口,在实际写php代码中不能用。因为只有内部的PHP类(用C写的类)才可以直接实现 Traversable接口。可以说这是个特性级别的东西。实际的PHP编程中我们使用Iterator接口或者IteratorAggregate接口 来实现遍历。

Traversable {
}

Traversable 接口不能直接实现(implements).Traversable 重要的一个用处就是判断一个类是否可以遍历:

if($class instanceof Traversable)
{
     //foreach...
}

下面是官方例子:

<?php
    if( !is_array( $items ) && !$items instanceof Traversable )
        //Throw exception here
?>

2. Iterator

Iterator接口的主要用途是允许一个类实现一个基本的迭代功能,从而使它可以被循环访问,根据键值访问以及回滚。Iterator接口摘要如下:

Iterator extends Traversable  
{  
    //返回当前索引游标指向的元素  
    abstract public mixed current(void)  
    //返回当前索引游标指向的元素的键名  
    abstract public scalar key(void)  
    //移动当前索引游标指向下一元素  
    abstract public void next(void)  
    //重置索引游标的指向第一个元素  
    abstract public void rewind(void)  
    //判断当前索引游标指向的是否是一个元素,常常在调用 rewind()或 next()使用  
    abstract public boolean valid(void)  
} 

外部迭代器接口,实现该接口的对象可以迭代自己内部的数据。

Iterator 的例子这里就不再列举了,本专题前面部分以后后续有很多例子,具体请自行查看。

3. IteratorAggregate

又叫聚合式迭代器。创建外部迭代器的接口,其摘要如下:

IteratorAggregate extends Traversable {  
	//实现该方法时,必须返回一个实现了Iterator接口的类的实例  
	abstract public Traversable getIterator ( void )  
} 

其中getIterator 方法返回值必须是能遍历或实现Iterator接口(must be traversable or implement interface Iterator)。SPL还提供了一些专门用来与IteratorAggregate接口一起使用的内置迭代器。使用这些迭代器意味着只需要实现一个方 法并实例化一个类就可以使对象可以迭代访问了。

实例:

/**
* @author 简明现代魔法 http://www.nowamagic.net
*/
class myData implements IteratorAggregate  
{  
    public $property1 = "公共属性1";  
    public $property2 = "公共属性2";  
    public $property3 = "公共属性3";  
  
    public function __construct()  
    {  
        $this->property4 = "最后一个公共属性";  
    }  
  
    public function getIterator()  
    {  
        return new ArrayIterator($this);  
    }  
}  
  
$obj = new myData;  
foreach ($obj as $key => $value) {  
    echo "键名:{$key}  值:{$value}\n";  
} 

程序输出:

键名:property1  值:公共属性1
键名:property2  值:公共属性2
键名:property3  值:公共属性3
键名:property4  值:最后一个公共属性

4. ArrayAccess

数组式访问接口。实现该接口的对象能像数组一样使用:

ArrayAccess {
	/* Methods */
	abstract public boolean offsetExists ( mixed $offset )
	abstract public mixed offsetGet ( mixed $offset )
	abstract public void offsetSet ( mixed $offset , mixed $value )
	abstract public void offsetUnset ( mixed $offset )
}
  • ArrayAccess::offsetExists — 检查一个偏移位置是否存在
  • ArrayAccess::offsetGet — 获取一个偏移位置的值
  • ArrayAccess::offsetSet — 设置一个偏移位置的值
  • ArrayAccess::offsetUnset — 复位一个偏移位置的值

举个栗子:

/**
* @author 简明现代魔法 http://www.nowamagic.net
*/
class obj implements arrayaccess {
    private $container = array();
    public function __construct() {
        $this->container = array(
            "one"   => 1,
            "two"   => 2,
            "three" => 3,
        );
    }
    public function offsetSet($offset, $value) {
        if (is_null($offset)) {
            $this->container[] = $value;
        } else {
            $this->container[$offset] = $value;
        }
    }
    public function offsetExists($offset) {
        return isset($this->container[$offset]);
    }
    public function offsetUnset($offset) {
        unset($this->container[$offset]);
    }
    public function offsetGet($offset) {
        return isset($this->container[$offset]) ? $this->container[$offset] : null;
    }
}

$obj = new obj;

var_dump(isset($obj["two"]));
var_dump($obj["two"]);
unset($obj["two"]);
var_dump(isset($obj["two"]));
$obj["two"] = "A value";
var_dump($obj["two"]);
$obj[] = 'Append 1';
$obj[] = 'Append 2';
$obj[] = 'Append 3';
print_r($obj);

5. Serializable

序列化接口。实现该接口的类不能使用__sleep() 和__wakeup().在serialize时不执行__destruct(),在unserialize不执行__construct()。

Serializable {
	/* Methods */
	abstract public string serialize ( void )
	abstract public mixed unserialize ( string $serialized )
}

实现此接口的类将不再支持 __sleep() 和 __wakeup()。不论何时,只要有实例需要被序列化,serialize 方法都将被调用。它将不会调用 __destruct() 或有其他影响,除非程序化地调用此方法。当数据被反序列化时,类将被感知并且调用合适的 unserialize() 方法而不是调用 __construct()。如果需要执行标准的构造器,你应该在这个方法中进行处理。

  • Serializable::serialize — 对象的字符串表示
  • Serializable::unserialize — 构造对象
Serializable {
	/* Methods */
	abstract public string serialize ( void )
	abstract public mixed unserialize ( string $serialized )
}

例子:

class obj implements Serializable {
    private $data;
    public function __construct() {
        $this->data = "My private data";
    }
    public function serialize() {
        return serialize($this->data);
    }
    public function unserialize($data) {
        $this->data = unserialize($data);
    }
    public function getData() {
        return $this->data;
    }
}

$obj = new obj;
$ser = serialize($obj);

$newobj = unserialize($ser);

var_dump($newobj->getData());

6. Closure

Closure {
	/* 方法 */
	__construct ( void )
	public static Closure bind ( Closure $closure , object $newthis [, mixed $newscope = 'static' ] )
	public Closure bindTo ( object $newthis [, mixed $newscope = 'static' ] )
}

这个具体还没研究,具体可以去看官方文档:http://www.php.net/manual/en/reserved.interfaces.php

原文发布于微信公众号 - php(phpdaily)

原文发表时间:2015-04-16

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏desperate633

五分钟搞懂hashCode()和equals()方法的原理常见的误区错误出现的原因

这两个方法最开发者来说是十分重要的,必须清楚的理解,但实际上,甚至很多经验丰富的Java开发者有时候也没有真正搞清楚这两个方法的使用和原理。当我们自定义了对象,...

725
来自专栏Java爬坑系列

C++指针类型识别正确姿势

  指针是C和C++中编程最复杂也是最有技巧的部分,但对于新手来说,指针无疑是最致命的,让很多人望而退步。不过很多事情都是从陌生开始,然后渐渐熟悉起来的,就像交...

1627
来自专栏進无尽的文章

Swift| 基础语法(二)

总结下 swift下的基础语法,里面涉及到:常量&变量、Swift中的数据类型、逻辑分支、循环、字符串相关、数组和字典、方法的书写调用等内容,考虑到阅读体验分多...

562
来自专栏枕边书

PHP正则中的捕获组与非捕获组

今天遇到一个正则匹配的问题,忽然翻到有捕获组的概念,手册上也是一略而过,百度时无意翻到C#和Java中有对正则捕获组的特殊用法,搜索关键词有PHP时竟然没有相关...

1639
来自专栏河湾欢儿的专栏

js基础

652
来自专栏超然的博客

es6 Object.assign

  Object.assign方法用来将源对象(source)的所有可枚举属性,复制到目标对象(target)。它至少需要两个对象作为参数,第一个参数是目标对象...

1163
来自专栏desperate633

LeetCode 17. Letter Combinations of a Phone Number题目分析代码

以上的答案是按照词典编撰顺序进行输出的,不过,在做本题时,你也可以任意选择你喜欢的输出顺序。

591
来自专栏好好学java的技术栈

”365算法每日学计划”:02打卡-线性表(赠书活动第①期预告)

1003
来自专栏mathor

LeetCode74. 搜索二维矩阵&240. 搜索二维矩阵 II

 通常情况下在一个矩阵中搜索一个元素时间复杂度是O(m*n)的,但是在这里只用O(m+n)的时间复杂度就能完成,说一下思路  以右上角为起点,如果当前的值...

512
来自专栏禁心尽力

mybatis_个人总结

在使用mybatis框架开发数据访问层的过程中,我在这段时间遇到很多细节问题困住我,在这里我来分享一下我遇到的坑,希望能帮到大家。 一、mybatis动态代理...

1646

扫描关注云+社区