介绍
PHP 中内置了一些预定义接口,接口实现后会获得一些特有的功能。
数组式访问(ArrayAccess)
提供像访问数组一样访问对象的能力的接口,实例如下:
<?php
class Item implements ArrayAccess
{
private $container;
public function __construct() {
$this->container = array(
"one" => 1,
"two" => 2,
"three" => 3,
);
}
public function offsetExists($offset)
{
return isset($this->container[$offset]);
}
public function offsetGet($offset)
{
return isset($this->container[$offset]) ? $this->container[$offset] : null;
}
public function offsetSet($offset, $value)
{
if (is_null($offset)) {
$this->container[] = $value;
} else {
$this->container[$offset] = $value;
}
}
public function offsetUnset($offset)
{
unset($this->container[$offset]);
}
}
$item = new Item();
echo $item['one']; //输出1
ArrayAccess 要求必须实现这个四个方法,但是对于方法里实现的内容并无定义,以数组方式访问时自动调用 offsetGet,isset 数据时自动调用offsetExists,如果将offsetGet 里的返回语句改成 'hello world' ,在以数组访问对象时,所有的输出都是 'hello world'。
迭代器接口(Iterator)
可在内部迭代自己的外部迭代器或类的接口,也就是能像操作数组遍历一下操作对象,实例如下:
<?php
class ArrayList implements Iterator
{
private $arr = ['one', 'two', 'three'];
private $position;
public function __construct()
{
$this->position = 0;
}
//返回当前元素
public function current()
{
return $this->arr[$this->position];
}
//向前移动到下一个元素
public function next()
{
++$this->position;
}
//返回当前元素的键
public function key()
{
return $this->position;
}
//检查当前位置是否有效
public function valid()
{
return isset($this->arr[$this->position]);
}
//返回到迭代器的第一个元素
public function rewind()
{
$this->position = 0;
}
}
$arrayList = new ArrayList();
foreach($arrayList as $key => $value){
var_dump($key, $value);
}
迭代器的接口方法也是可以自定义实现内容的,该接口的意义在于对于不同的数据类型,外部的迭代器不需要关系内部的实现方法,只需要按照统一的标准进行遍历就可以了。
聚合式迭代器接口(IteratorAggregate)
创建外部迭代器的接口,通过数组式访问的接口虽然可以实现对象的数组式访问,但是无法使用 foreach 遍历,可以通过该接口实现数据和迭代器的分离,从而可以使用 foreach 遍历。
<?php
class Item implements IteratorAggregate
{
private $container;
public function __construct() {
$this->container = array(
"one" => 1,
"two" => 2,
"three" => 3,
);
}
public function getIterator()
{
return new ArrayIterator($this->container);
}
}
$item = new Item();
foreach($item as $key => $value){
var_dump($value);
}
序列化接口(Serializable)
自定义序列化接口,实现此接口的类,在类进行序列化或反序列化时,可根据内部实现的方法处理数据,同时,实现该接口的类将不再支持 __sleep() 和 __wakeup()
<?php
class Item 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);
}
}
$item = new Item;
$ser = serialize($item);
$item_obj = unserialize($ser);
匿名函数类(Closure)
PHP 中所有的匿名函数都是这个类的对象实例,但匿名函数的创建过程和该类无关,用来操作匿名函数的,有三个方法 __construct,bind, bindTo。
__construct:禁止实例化Closure对象,自动完成,不需要操作。
Closure::bind: 是 bindTo 的静态方法,用来复制一个闭包绑定到指定类和作用域。
class A {
public static $sfoo = 1;
private $ifoo = 2;
}
//静态匿名函数可以防止它们将当前类自动绑定到它们
$cl1 = static function() {
return A::$sfoo;
};
$cl2 = function() {
return $this->ifoo;
};
$bcl1 = Closure::bind($cl1, null, 'A');
$bcl2 = Closure::bind($cl2, new A(), 'A');
echo $bcl1(), "\n"; //1
echo $bcl2(), "\n"; //2
Closure::bindTo: 复制当前闭包对象,绑定指定的$this对象和类作用域。
class A {
function __construct($val) {
$this->val = $val;
}
function getClosure() {
return function() { return $this->val; };
}
}
$ob1 = new A(1);
$ob2 = new A(2);
$cl = $ob1->getClosure();
echo $cl(), "\n"; //1
$cl = $cl->bindTo($ob2);
echo $cl(), "\n"; //2
网友评论