如何建立壹個類及類的實例對象?
在PHP中通過類來完成封裝,我們先看壹個簡單的例子:
<?php //定義類
class ClassName {
//定義數據成員用"var",數據成員可以是壹個整數,壹個數組,壹個相關數組(associative array)或者是壹個對象
var $value;
//方法在類中被定義成函數形式,在方法中訪問類成員變量時,可以使用$this->name ,比如$this->setValue
function setValue($v) {
$this->value=$v;
}
function getValue() {
return $this->value;
}
}
//創建壹個對象用"new"操作符
$obj=new ClassName;
$obj->setValue("Hello,PHP world!");
$obj->getValue();
?>
繼承用"extend"關鍵字。例如:
<?php
class HelloPHPWorld extends ClassName {
var $message;
function setMessage($msg) {
$this->message=$msg;
}
function getMessage() {
return $this->message;
}
}
?>
"HelloPHPWorld"類的對象現在擁有了父類(ClassName)的全部的數據成員及方法,另外還有自已的數據成員和方法。
我們可以使用:
$obj2=new HelloPHPWorld;
$obj2->setValue("I love world!");
$obj2->setMessage("I love PHP!");
PHP現在還不支持多重繼承,所以不能從兩個或兩個以上類派生出新的類來。
如何在派生類中重定義壹個方法?
我們可以在派生類中重定義壹個方法,如果我們在"HelloPHPWorld"類中重定義了getValue方法,我們就不能使用"ClassName"中的getValue方法了。如果我們在派生類中聲明了壹個與基派同名的數據成員,那麽當我們處理它時,它將"隱藏"基類的數據成員。
如何在類中定義構造函數?
構造函數是壹個與類名同名的方法,當創建壹個類的對象時,該函數會被調用以用來初始化對象,例如定義壹個類:
<?php
class ClassName {
var $value;
function ClassName($v) {
$this->value=$v;
}
function setValue($v) {
$this->value=$v;
}
function getValue() {
return $this->value;
}
}
?>
上例中,類中的成員函數ClassName即壹個構造函數,現在我們可以這樣創建對象:
$obj=new ClassName("Hello,PHP world!");
將參數傳遞給構造函數,構造函數則會自動地將"Hello,PHP world!"賦值給函數中的數據變量value。構造函數和方法都是普通的PHP函數,所以可以使用缺省參數。
function ClassName($k="welcome",$v="Hello,PHP world!")
接著:
$obj=new ClassName(); // $key="welcome",value="Hello,PHP world!"
$obj=new ClassName("I love PHP!"); // $key="welcome",value="I love PHP!"
$obj=new ClassName("First","I love PHP!"); // $key="First",value="I love PHP!"
缺省參數使用C++的方式,參數是從左到右賦值的,如果傳入的參數少於要求的參數時,其余的將使用缺省參數。
當壹個派生類的對象被創建時,只有它的構造函數被調用,父類的構造函數沒被調用,如果妳想調用基類的構造函數,妳必須要在派生類的構造函數中顯式調用。可以這樣做是因為在派生類中所有父類的方法都是可用的。
<?php
function HelloPHPWorld() {
$this->message="Hello,PHP world!";
$this->ClassName();
//顯式調用基類構造函數
}
?>
在PHP中沒有標準的方法來實現抽象類,但是如果需要這個特性,可以通過定義基類,並在它的構造函數後加上"die" 的調用,這樣就可以保證基類是不可實例化的,現在在每壹個方法(接口)後面加上"die" 語句,所以,如果壹個程序員在派生類中沒有覆蓋方法,將引發壹個錯誤。而且因為PHP 是無類型的,所以可能需要確認壹個對象是來自於基類的派生類,那麽在基類中增加壹個方法來實義類的身份(返回某種標識id),並且在接收到壹個對象參數時校驗這個值。
如何在PHP中實現析構函數功能?
在OOP中,我們可以重載壹個方法來實現兩個或重多的方法具有相同的名字,但是有不同數量或類型的參數(這要看語言)。PHP 是壹種松散類型的語言,沒有析構函數,所以通過類型重載或者通過參數的個數不同來重載也沒有作用。
有時在OOP中重載構造函數非常好,這樣可以通過不同的方法創建對象(傳遞不同數量的參數)。而在PHP中,怎麽去實現同等的功能呢?技巧如下:
<?php
class Myclass {
function Myclass() {
$name="Myclass".func_num_args();
$this->$name();
//註意$this->name()壹般是錯誤的,但是在這裏$name是壹個將被調用方法的名字
}
function Myclass1($x) {
……
}
function Myclass2($x,$y) {
……
}
}
?>
通過在類中的額外的處理,使用這個類對用戶是透明的:
$obj1=new Myclass('1'); //將調用Myclass1
$obj2=new Myclass('1','2'); //將調用Myclass2
如何在PHP中應用多態性?
多態性在象PHP這樣的解釋語言是非常容易和自然的:
<?php
function niceDrawing($x) {
//假設這是Board類的壹個方法
$x->draw();
}
$obj=new Circle(3,187);
$obj2=new Rectangle(4,5);
$board->niceDrawing($obj);
//將調用Circle的draw方法
$board->niceDrawing($obj2);
//將調用Rectangle的draw方法
?>
如何應用序列化(Serializing) 機制?
PHP不支持永久對象,而在OOP中永久對象是可以在多個應用的引用中保持狀態和功能的對象,這意味著擁有將對象保存到壹個文件或數據庫中的能力,而且可以在以後裝入對象。這就是所謂的序列化機制。PHP 擁有序列化方法,它可以通過對象進行調用,序列化方法可以返回對象的字符串表示。然而,序列化只保存了對象的成員數據而不包話方法。
例子 :
<?php
$obj=new Classfoo();
$str=serialize($obj);
//保存$str到磁盤上
//幾個月以後
//從磁盤中裝入str
$obj2=unserialize($str)
?>
恢復了成員數據,但是不包括方法。這導致了只能通過類似於使用$obj2->x來存取成員變量的唯壹辦法。
如何使用類進行數據存儲?
對於PHP和OOP,可以很容易地定義壹個類來操作某件事情,並且無論何時妳想用的時候都可以調用相應的類。我們可以使用OOP或PHP來減少編碼並提高質量。
定義壹個產品的類,定義它應該有的方法(例如:顯示),然後定義對每壹種類型的產品的類,從產品類派後出來(SoundItem類,ViewableItem類,等等),覆蓋在產品類中的方法,使它們按我們的預想運作。
根據數據庫中每壹種產品的類型(type)字段給類命名,壹個典型的產品表可能有(id, type, price, description)等等字段,然後在處理腳本中,可以從數據庫中取出type值,然後實例化壹個名為type的對象:
<?php
$obj=new $type();
$obj->action();
?>
這是PHP的壹個非常好的特性,不用考慮對象的類型,調用$obj的顯示方法或其它的方法。不需要修改腳本去增加壹個新類型的對象,只是增加壹個處理它的類。
當創建壹個$obj的對象時,可以通過$obj2=$obj來拷貝對象,新的對象是$obj的壹個拷貝(不是壹個引用),所以它具有$obj在當時的狀態。有時候,只是想生成壹個象obj類壹樣的壹個新的對象,可以通過使用new語句來調用類的構造函數。在PHP中也可以通過序列化,和壹個基類來實現,但所有的其它類都要從基類派生出來。
當序列化壹個對象,會得到某種格式的字符串,其中,字符串中有類的名字,可以把它取出來,比如:
<?php
$herring=serialize($obj);
$vec=explode(':',$herring);
$nam=str_replace("\"",'',$vec[2]);
?>
所以假設創建了壹個"Universe"的類,並且強制所有的類都必須從universe擴展,可以在universe中定義壹個clone的方法,如下:
<?php
class Universe {
function clone() {
$herring=serialize($this);
$vec=explode(':',$herring);
$nam=str_replace(""",'',$vec[2]);
$ret=new $nam;
return $ret;
}
}
//然後
$obj=new Something();
//從Universe擴展
$other=$obj->clone();
?>
所得到的是壹個新的Something類的對象,它同使用new方法,調用構造函數創建出的對象壹樣。