雖然寫這種東西點閱率應該很低,不過,可以充很大的版面(沒有誤),也算是功德一件。
這次要筆記的東西,是 PHP 5 的一些新東西,還有順便是從 TextCube Night build 中找到的一些新玩意。俗話說得好,拷貝是學習的不二法門 (肯定的),但是單純的拷貝並不會進步,我作筆記總可以吧 (哈哈哈)。
首先是 Abstract Class (抽象類別) 與 Interface (介面) 的介紹,在 php.net 裡面對於 Interface 的介紹少之又少,所以跑去問問估狗大神,還不少資料,繁簡體都有。
我這邊整理一下。
Interface
只是定義一個介面,這個介面裡面可以放 private
, public
, protected
三種類型的函式、變數。當然,除了 public
之外,除非必要,我想大概不會想放其它兩種。都要用來 implements
了,不 public
的話要怎麼 implements
呢 (笑)。
implements
(實作) 跟 extends
(繼承或衍生,因程序而異) 這兩者應該不難見,只是 extends
好像比較常見就是。
以下整理自出處:http://ronnywang.pixnet.net/blog/post/19130725
我在這邊另外附上實作範例,幫助了解。
interface Iterator {
public function rewind();
public function current();
public function key();
public function next();
public function valid();
}
interface IteratorAggregate {
public function getIterator();
}
Iterator
跟 IteratorAggregate
兩者,是一種迴圈介面,可以被 foreach
或是 for
迴圈使用。後者是指定迴圈最大值 (總值),並傳回給前者,當然,這樣的回傳動作需要 implements Class
去做,以下給各位一個實作範例比較清楚。另外,這兩種 (甚至接下來回提到的 Interface
都是 PHP 5 已經內建的,不需要再定義了)。
<?php
class CI implements Iterator {
private $obj;
private $num;
public function __construct($obj) {
$this->obj = $obj;
}
public function rewind() {
$this->num = 0;
}
public function valid() {
return $this->num < $this->obj->max;
}
public function key() {
return $this->num;
}
public function current() {
switch($this->num) {
case 0: return "1st";
case 1: return "2nd";
case 2: return "3rd";
default: return $this->num."th";
}
}
public function next() {
$this->num++;
}
}
class CIA implements IteratorAggregate {
public $max = 1;
public function getIterator() {
return new CI($this);
}
}
// class CI 與 CIA 是自己取的名稱(這是廢話吧)
$obj = new CIA;
// 指定這個 IteratorAggregate 的最大值(在 Class CIA 裏面我預設給 1 而已)
$obj->max = 10;
// 使用 foreach
echo '使用 foreach...<br /> ';
foreach($obj as $key => $val) {
echo $key,' = ',$val,'<br />';
}
// 相當於使用 for 迴圈的用法
echo '相當於使用 for 迴圈的用法...<br /> ';
$it = $obj->getIterator();
for($it->rewind(); $it->valid(); $it->next()) {
$val = $it->current();
$key = $it->key();
echo $key,' = ',$val,'<br />';
}
unset($it);
/* 顯示結果
使用 foreach...
0 = 1st
1 = 2nd
2 = 3rd
3 = 3th
4 = 4th
5 = 5th
6 = 6th
7 = 7th
8 = 8th
9 = 9th
相當於使用 for 迴圈的用法...
0 = 1st
1 = 2nd
2 = 3rd
3 = 3th
4 = 4th
5 = 5th
6 = 6th
7 = 7th
8 = 8th
9 = 9th
*/
Countable 可以將 implements class 做 count 使用。
interface Countable {
public function count();
}
<?php
class CI implements Countable {
private $intCount = null;
public function __construct($intCount){
$this->intCount = $intCount;
}
public function count(){
return $this->intCount;
}
}
$obj = new CI(15);
echo count($obj).'<br />';
echo $obj->count().'<br />';
/* 顯示結果
15
15
*/
有人大概會問說,為什麼不用 $obj[$pos]
去取結果值,這樣是不行的,因為陣列的方式必須使用另一個 interface ArrayAccess
的方式去做。
interface SeekableIterator {
public function rewind();
public function current();
public function key();
public function next();
public function valid();
public function seek($pos);
}
<?php
class CI implements SeekableIterator {
private $obj;
private $num;
public function __construct($obj) {
$this->obj = $obj;
}
public function rewind() {
$this->num = 0;
}
public function valid() {
return $this->num < $this->obj->max;
}
public function key() {
return $this->num;
}
public function current() {
switch($this->num) {
case 0: return "1st";
case 1: return "2nd";
case 2: return "3rd";
default: return $this->num."th";
}
}
public function next() {
$this->num++;
}
public function seek($pos) {
$__tmp = $this->num;
$this->num = $pos;
$pos = $this->current();
$this->num = $__tmp;
return $pos;
}
}
class CIA implements IteratorAggregate {
public $max = 1;
function getIterator() {
return new CI($this);
}
}
$obj = new CIA;
// 指定這個 IteratorAggregate 的最大值(在 Class CIA 裏面我預設給 1 而已)
$obj->max = 10;
// 這裡僅介紹 seek 的用法,其它迴圈用法與 Iterator, IteratorAggregate 相同
$it = $obj->getIterator();
echo $it->seek(5);
/* 顯示結果
5th
*/
底下來介紹 ArrayAccess,這是 ArrayAccess 在 PHP 裡面的定義。
interface ArrayAccess {
offsetExists ($offset) // boolean
offsetGet ($offset) // mixed
offsetSet ($offset, $value) // void
offsetUnset ($offset) // void
}
簡單的範例如下。
class CI implements ArrayAccess {
private $configarray;
public function __construct() {
$this->configarray = array("John"=>"Male", "May"=>"Female");
}
public function offsetExists($index) {
return isset($this->configarray[$index]);
}
public function offsetGet($index) {
return $this->configarray[$index];
}
public function offsetSet($index, $newvalue) {
$this->configarray[$index] = $newvalue;
}
public function offsetUnset($index) {
unset($this->configarray[$index]);
}
}
$obj = new CI();
echo '原有陣列為:array("John"=>"Male", "May"=>"Female")<br />';
echo 'offsetGet("May") => '.($obj->offsetGet("May")).'<br />';
echo 'offsetExists("May") => ';
echo ($obj->offsetExists("May")) ? 'yes' : 'no';
echo '<br />';
$obj->offsetSet("May", "John's wife.");
// 使用 offsetSet 修改原有陣列內的值
echo '使用 offsetSet 修改原有陣列內的值<br />';
echo 'offsetGet("May") => '.($obj->offsetGet("May")).'<br />';
// 使用 offsetSet 新增原有陣列內的值
echo '使用 offsetSet 新增原有陣列內的值<br />';
$obj->offsetSet("Jasmin", "John's sister.");
echo 'offsetGet("Jasmin") => '.($obj->offsetGet("Jasmin")).'<br />';
echo '目前陣列內容為:array("John"=>"Male", "May"=>"John\'s wife.", "Jasmin", "John\'s sister.")<br />';
// 使用 offsetUnset 刪除原有陣列內的值
$obj->offsetUnset("May");
echo 'offsetExists("May") => ';
echo ($obj->offsetExists("May")) ? 'yes' : 'no';
echo '<br />';
echo '目前陣列內容為:array("John"=>"Male", "Jasmin", "John\'s sister.")<br />';
/* 顯示結果
原有陣列為:array("John"=>"Male", "May"=>"Female")
offsetGet("May") => Female
offsetExists("May") => yes
使用 offsetSet 修改原有陣列內的值
offsetGet("May") => John's wife.
使用 offsetSet 新增原有陣列內的值
offsetGet("Jasmin") => John's sister.
目前陣列內容為:array("John"=>"Male", "May"=>"John's wife.", "Jasmin", "John's sister.")
offsetExists("May") => no
目前陣列內容為:array("John"=>"Male", "Jasmin", "John's sister.")
*/
這個就應該比較容易理解,其實跟 serialize 差不多。這裡有一篇文章有非常詳盡的說明,值得一看:PHP 序列化(serialize)格式详解
interface Serializable {
public function serialize();
public function unserialize($serialized)
}
至於範例,我不想舉了,因為這牽扯到一些傳值傳址的問題,強烈建議閱讀我上面所提供的那篇文章。
誒... Abstract Class
呢?
我好懶啊... 請自行翻閱:
- SPL - Standard PHP Library
- PHP5 OO
- [PHP] 該用 Abstract Class 還是 Interface
- PHP5 的個體導向能力問題 - magic methods 和 interface
- Stack - Example for Operators of Array Overload
- SPL:Use ArrayObject and ArrayIterator to Overload Operators of Array
- 類與物件(PHP5)之七:多載(Overloading)
- 類與物件(PHP5)之八:物件叠代(Object Iteration)
- 類與物件(PHP5)之九:模式(Patterns)
- 類與物件(PHP5)之十:魔法方法(Magic Methods)
- 類與物件(PHP5)之十一:最終關鍵字(Final Keyword)
- 類與物件(PHP5)之十二:物件克隆(Object cloning)
- 類與物件(PHP5)之十三:物件比較(Comparing objects)
- 類與物件(PHP5)之十四:對應(反射)Reflection
- 類與物件(PHP5)之十五:典型提示(線索)Type Hinting
- PHP強制物件類型之instanceof運運算元(1)
- PHP強制物件類型之instanceof運運算元(2)
- PHP強制物件類型之instanceof運運算元(3)
- Memcached深度分析
先告一段落,以後想到什麼在補上吧。
附帶一提,TextCube 從 1.8 以後的程式結構又改了,不知道對往後修改有無影響?目前縱觀而言,似乎是沒有 (遠目)。