1. 程式人生 > 其它 >PHP Predefined Interfaces 預定義介面

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