国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > PHP > 正文

自定義PHP數(shù)組類的實現(xiàn)

2019-11-08 03:12:32
字體:
供稿:網(wǎng)友

php一開始是面向過程的語言,到后期才支持面向?qū)ο螅瑪?shù)組在php中的類型是 “array”:

echo gettype(array());

輸出

array

很多操作數(shù)組的函數(shù)都是以 “array” 開頭,第一個參數(shù)為要操作的數(shù)組。

要實現(xiàn)一個數(shù)組類,需要實現(xiàn)Arrayaccess這個接口,這個接口的功能是 “提供像訪問數(shù)組一樣訪問對象的能力” ,該接口有四個方法:

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 )

這四個函數(shù)的作用如下(假設(shè)$obj是一個實現(xiàn)了該接口的類的實例):

offsetExists, 執(zhí)行isset( $obj[$key])時觸發(fā)offsetGe,獲取$obj[$key]時觸發(fā)offsetSet, 執(zhí)行 $obj[$key] = $value時觸發(fā)offsetUnset, 執(zhí)行unset($obj[$key])時觸發(fā)

看上去有點類似C++的運算符重載。我們可以封裝一個類,以一個數(shù)組變量作為其私有屬性,這四個函數(shù)操作數(shù)組變量就行。

且看代碼: 我們把這個類命名為XArray。

class XArray implements ArrayAccess{ PRivate $container = array(); public function __construct($size = 0, $value = 0) { if ($size > 0) { $this->container = array_fill(0, $size, $value); } } public function offsetSet($offset, $value) { echo "call ", __METHOD__, PHP_EOL; if(is_null($offset)) { $this->container[] = $value; } else { $this->container[$offset] = $value; } } public function offsetUnset($offset) { echo "call ", __METHOD__, PHP_EOL; unset($this->container[$offset]); } public function offsetGet($offset) { echo "call ", __METHOD__, PHP_EOL; return isset($this->container[$offset]) ? $this->container[$offset] : null; } public function offsetExists($offset) { echo "call ", __METHOD__, PHP_EOL; return isset($this->container[$offset]); }}

測試:

$obj = new XArray(5, 10);$obj[] = 16;echo $obj['a'];isset($obj[3]);unset($obj['a']);

輸出:

call XArray::offsetSetcall XArray::offsetGetcall XArray::offsetExistscall XArray::offsetUnset

正如以上分析所言。

我們可以像操作數(shù)組一樣操作一個XArray類的實例,可是對于便利操作(foreach),就不行了。

foreach ($obj as $v) { echo $v;}

沒有輸出。

要能讓XArray的實例實現(xiàn)遍歷操作,得實現(xiàn)Traversable接口,但這是個抽象接口,不過Iterator接口繼承了Traversable接口,所以我們可以實現(xiàn)Iterator接口。這個接口有5個方法:

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 )

各方法的作用如下:

current, 返回當(dāng)前元素key, 返回當(dāng)前元素的鍵next, 移動到下一個元素rewind, 返回迭代器的第一個元素valid, 在rewind和next方法之后調(diào)用,檢查當(dāng)前位置是否有效

在XArray中增加一個$position私有變量,然后增加以下5個方法:

public function rewind() { echo "call ", __METHOD__, PHP_EOL; reset($this->container); $this->position = 0; } public function current() { echo "call ", __METHOD__, PHP_EOL; return current($this->container); } public function next() { echo "call ", __METHOD__, PHP_EOL; next($this->container); $this->position++; } public function key() { echo "call ", __METHOD__, PHP_EOL; return key($this->container); } public function valid() { echo "call ", __METHOD__, PHP_EOL; return $this->position < count($this->container); }

有rewind, current,next,key這4個方法,內(nèi)部都是通過調(diào)用php操作數(shù)組的相應(yīng)方法來實現(xiàn)的。

測試:

$obj = new XArray();$obj[] = 1;$obj[] = 2;$obj[] = 3;foreach ($obj as $v) { echo $v, PHP_EOL;}

輸出:

call XArray::offsetSetcall XArray::offsetSetcall XArray::offsetSetcall XArray::rewindcall XArray::validcall XArray::current1call XArray::nextcall XArray::validcall XArray::current2call XArray::nextcall XArray::validcall XArray::current3call XArray::nextcall XArray::valid

由以上輸出可知,首次遍歷時,依次調(diào)用rewind, valid方法, 然后調(diào)用current方法得到值;后面都是依次調(diào)用next, valid方法,再調(diào)用current方法得到值。如果valid方法返回false,說明遍歷到了末尾,則不再調(diào)用current方法,遍歷結(jié)束。

可以看到,用 foreach($obj as $v)這種遍歷方式,并沒有調(diào)用key方法。

我們把遍歷方式改為foreach($obj as $k => $v)試一下:

$obj = new XArray();$obj[] = 1;$obj[] = 2;$obj[] = 3;foreach ($obj as $k => $v) { echo $v, PHP_EOL;}call XArray::offsetSetcall XArray::offsetSetcall XArray::offsetSetcall XArray::rewindcall XArray::validcall XArray::currentcall XArray::key1call XArray::nextcall XArray::validcall XArray::currentcall XArray::key2call XArray::nextcall XArray::validcall XArray::currentcall XArray::key3call XArray::nextcall XArray::valid

這次有調(diào)用key方法了,而且可以看到, key方法是在current方法調(diào)用之后才調(diào)用的。

這樣的數(shù)組類,功能還是有點弱,很多數(shù)組的方法都沒有,比如,push, pop, slice, 也不能獲取數(shù)組長度(length屬性)。

在XArray類中添加如下代碼:

public function all() { return $this->container; } /** $obj->length 獲取數(shù)組元素個數(shù) */ public function __get($property) { if ($property == 'length') { return count($this->container); } return null; } /** 把一個XArray類的實例,數(shù)組或其他類型的變量合并到本實例的數(shù)組變量中 */ public function merge($data) { $class = get_class($this); if ($data instanceof $class) { $this->container = array_merge($this->container, $data->all()); } elseif (is_array($data)) { $this->container = array_merge($this->container, $data); } else{ $this->container[] = $data; } return $this; } public function shift() { return array_shift($this->container); } public function pop() { return array_pop($this->container); } public function push($ele) { foreach (func_get_args() as $v) { array_push($this->container, $v); } return $this; } public function unshift($ele) { foreach (func_get_args() as $v) { array_unshift($this->container, $v); } return $this; } public function slice($offset, $length) { $arr = array_slice($this->container, $offset, $length); if (empty($arr)) { return null; } $class = get_class($this); $obj = new $class(); return $obj->merge($arr); } /** 打印實例內(nèi)容 */ public function dump() { echo "[elements begin]", PHP_EOL; foreach ($this->container as $k => $v) { echo "/t",$k, " => ", $v, PHP_EOL; } echo "[elements end]", PHP_EOL; }

大部分函數(shù)都是調(diào)用php的同名array_系列數(shù)組操作函數(shù),其中unshift, push方法最后時return $this,可以實現(xiàn)鏈?zhǔn)秸{(diào)用, slice方法則是返回一個XArray對象。

測試代碼:

$obj = new XArray(2, 6);$obj[] = 16;$obj->push(1,2,3)->unshift(5)->pop();$obj->dump();echo "len(obj) = ", $obj->length, PHP_EOL;$obj2 = $obj->slice(0, 3);$obj2->dump();

輸出:

call XArray::offsetSet[elements begin] 0 => 5 1 => 6 2 => 6 3 => 16 4 => 1 5 => 2[elements end]len(obj) = 6[elements begin] 0 => 5 1 => 6 2 => 6[elements end]

如預(yù)期。

由于時間有限,數(shù)組操作的其他功能就不實現(xiàn)了。之前查看Laravel的源碼,有個文件也是實現(xiàn)了一個數(shù)組類,很多數(shù)組操作的方法都實現(xiàn)了。


發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 安平县| 高雄县| 从化市| 沙洋县| 岳阳市| 任丘市| 诏安县| 巴南区| 桐梓县| 青河县| 甘孜| 张家口市| 蓬溪县| 庆城县| 天全县| 綦江县| 象山县| 墨竹工卡县| 盐池县| 宣汉县| 宝清县| 阆中市| 武邑县| 平泉县| 宜黄县| 桓台县| 集贤县| 太仓市| 临安市| 海兴县| 鄂尔多斯市| 博乐市| 诸城市| 廊坊市| 溆浦县| 东乌| 台南市| 吉安县| 桂平市| 玛沁县| 武威市|