日期:2006-10-16 作者:喜騰小二 來源:PHPChina
PHP5 中的三大特色功能。這三大特點為:
* 新的物件模式 (New Object Mode)
* 異常處理 (Exceptions)
* 名稱空間 (Namespace)
在開始之前,要宣告兩點:
* 文章中的例子為了幫助如何操作,有些部分使用了 PHP4 的表現手段,這僅僅是為了提高文章的可讀性。
* 文章中描述的部分與 PHP5 的最終發佈版可能會有一些出入
在 PHP5 沒有最終正式發佈前,妳可以隨時從 http://snaps.php.net 下載到最新的編譯版本來親自體驗一下 PHP5 所帶給我們這些嶄新的功能。
新的物件模式
PHP5 中的物件已經進行了較係統、較全麵的調整,現在的樣子可能看起來會有些類似於 Java。本小節着重講述 PHP5 中新的物件模式,並舉了一些較簡易的例子來幫助。就讓本節成為妳的 PHP5 之旅的一個新起點吧。:)
* 構造函式和析構函式
* 物件的引用
* 物件的克隆
* 物件中的私有、公共及受保護模式
* 介麵 (Interfaces)
* 抽象類
* __call
* __set 和 __get
* 靜態成員
構造函式和析構函式
在 PHP4 中,當函式與物件同名時,這個函式將成為該物件的構造函式,並且在 PHP4 中沒有析構函式的概念。
在 PHP5 中,構造函式被統一命名為 __construct,並且引入了析構函式的概念,被統一命名為 __destruct。
例一:構造函式和析構函式
class foo {
var $x;
function __construct($x) {
$this->x = $x;
}
function display() {
print($this->x);
}
function __destruct() {
print("bye bye");
}
}
$o1 = new foo(4);
$o1->display();
?>
在上麵的例子中,當妳終止調用 foo 類的時候,其析構函式將會被調用,上例中會輸出 “bye bye”。
物件的引用
眾所周知,在PHP4 中,傳遞變數給一個函式或方法,實際是把這個變數做了一次複製,也就意味着妳傳給函式或方法的是這個變數的一個副本,除非妳使用了引用符號 “&” 來宣告是要做一個引用,而不是一個 Copy。在 PHP5 中,物件總是以引用的形式存在的,物件中的賦值操作同樣也都是一個引用操作。
例二:物件的引用
class foo {
var $x;
function setX($x) {
$this->x = $x;
}
function getX() {
return $this->x;
}
}
$o1 = new foo;
$o1->setX(4);
$o2 = $o1;
$o1->setX(5);
if($o1->getX() == $o2->getX()) print("Oh my god!");
?>
物件的克隆
如上所述,當一個物件始終以引用的形式來被調用時,如果我想得到該物件的一個副本,該怎麼辦呢?PHP5 提供了一個新的功能,就是物件的克隆,語法為 __clone。
例三:物件的克隆
class foo {
var $x;
function setX($x) {
$this->x = $x;
}
function getX() {
return $this->x;
}
}
$o1 = new foo;
$o1->setX(4);
$o2 = $o1->__clone();
$o1->setX(5); if($o1->getX() != $o2->getX()) print("Copies are independant");
?>
物件克隆的方法在其它很多應用程式語言中都是存在的,所以妳不必擔心它的穩定性。:)
物件中的私有、公共及保護模式
PHP4 中,一個物件的所有方法和變數都是公共的,這意味着妳可以在一個物件的外部操作其中的任意一個變數和方法。PHP5 引入了三種新的用來控制這種存取授權權的模式,它們是:公共的(Public)、受保護的(Protected)及私有的(Private)。
公共模式(Public):允許在物件外部進行操作控制。
私有模式(Private):隻允許本物件內的方法對其進行操作控制。
受保護模式(Protected):允許本物件及其父物件對其進行操作控制。
例四: 物件中的私有、公共及受保護模式
class foo {
private $x;
public function public_foo() {
print("I'm public");
}
protected function protected_foo() {
$this->private_foo(); //Ok because we are in the same class we can call private methods
print("I'm protected");
}
private function private_foo() {
$this->x = 3;
print("I'm private");
}
}
class foo2 extends foo {
public function display() {
$this->protected_foo();
$this->public_foo();
// $this->private_foo(); // Invalid! the function is private in the base class
}
} $x = new foo();
$x->public_foo();
//$x->protected_foo(); //Invalid cannot call protected methods outside the class and derived classes
//$x->private_foo(); //Invalid private methods can only be used inside the class $x2 = new foo2();
$x2->display();
?>
提示:物件中的變數總是以私有形式存在的,直接操作一個物件中的變數不是一個好的麵嚮物件編程的習慣,更好的辦法是把妳想要的變數交給一個物件的方法去處理。
介麵 (Interfaces)
眾所周知,PHP4 中的物件支援繼承,要使一個物件成為另一個物件的派生類,妳需要使用類似 “class foo extends parent” 的程式碼來控制。 PHP4 和 PHP5 中,一個物件都僅能繼承一次,多重繼承是不被支援的。不過,在 PHP5 中產生了一個新的名詞:介麵,介麵是一個沒有俱體處理程式碼的特殊物件,它僅僅定義了一些方法的名稱及參數,此後的物件就可以方便的使用 'implement' 關鍵字把需要的介麵整合起來,然後再加入俱體的執行程式碼。
例五:介麵
interface displayable {
function display();
}
interface printable {
function doprint();
}
class foo implements displayable,printable {
function display() {
// code
} function doprint() {
// code
}
}
?>
這對提高程式碼的可讀性及通俗性有很大的說明,透過上麵的例子可以看到,物件 foo 包含了 displayable 和 printable 兩個介麵,這時我們就可以清楚的知道,物件 foo 一定會有一個 display() 方法和一個 print() 方法,隻需要去瞭解介麵部分,妳就可以輕易的操作該物件而不必去關心物件的內部是如何運作的。
抽象類
抽象類不能被實例化。
抽象類與其它類一樣,允許定義變數及方法。
抽象類同樣可以定義一個抽象的方法,抽象類的方法不會被執行,不過將有可能會在其派生類中執行。
例六:抽象類
abstract class foo {
protected $x;
abstract function display();
function setX($x) {
$this->x = $x;
}
}
class foo2 extends foo {
function display() {
// Code
}
}
?>
__call
PHP5 的物件新增了一個私用方法 __call(),這個方法用來監視一個物件中的其它方法。如果妳試着調用一個物件中不存在的方法,__call 方法將會被自動調用。
例七:__call
class foo {
function __call($name,$arguments) {
print("Did you call me? I'm $name!");
}
} $x = new foo();
$x->doStuff();
$x->fancy_stuff();
?>
__call 實現“過載”動作
這個特殊的方法可以被用來實現“過載(overloading)”的動作,這樣妳就可以檢查妳的參數並且透過調用一個私有的方法來傳遞參數。
例八:使用 __call 實現“過載”動作
class Magic {
function __call($name,$arguments) {
if($name=='foo') {
if(is_int($arguments[0])) $this->foo_for_int($arguments[0]);
if(is_string($arguments[0])) $this->foo_for_string($arguments[0]);
}
} private function foo_for_int($x) {
print("oh an int!");
} private function foo_for_string($x) {
print("oh a string!");
}
} $x = new Magic();
$x->foo(3);
$x->foo("3");
?>
> __set 和 __get
這是一個很棒的方法,__set 和 __get 方法可以用來擷取一個物件中不存在的變數和方法。
例九: __set 和 __get
class foo {
function __set($name,$val) {
print("Hello, you tried to put $val in $name");
}
function __get($name) {
print("Hey you asked for $name");
}