面向對象編程的概念對每一個作者來說都有不同的看法
我提醒一下一個面向對象語言應有的東西
數據抽象和信息隱藏
繼承
多態性
在PHP中使用類進行封裝的辦法
class Something {
// In OOP classes are usually named starting with a cap letter
var $x;
function setX($v) {
// Methods start in lowercase then use lowercase to seprate
// words in the method name example getValueOfArea()
$this
>x=$v;
}
function getX() {
return $this
>x;
}
}
?>
當然你可以用你自己的辦法
但有一個標准總是好的
PHP中類的數據成員使用
var
定義
數據成員是沒有類型直到被賦值
一個數據成員可能是一個 integer
數組
聯合數組(associative array)或甚至對象(object)
方法在類裡定義成函數
在方法裡存取數據成員
你必須使用$this
>name 這樣的辦法
否則對方法來說是一個函數的局部變量
使用 new 來創建一個對象
$obj = new Something;
然後使用成員函數
$obj
>setX(
);
$see = $obj
>getX();
setX 成員函數將
賦給對象(而不是類)obj 中成員變量
然後 getX 返回值
你也可以用對象引用來存取成員變量
例如
$obj
>x=
; 然而
這不一種好的面向對象編程的方法
我堅持你應使用成員函數來設置成員變量的值和通過成員函數來讀取成員變量
如果你認為成員變量是不可存取的除了使用成員函數的辦法
你將成為一個好的面向對象程序員
但不幸的是PHP本身沒有辦法聲明一個變量是私有的
所以允許糟糕的代碼存在
在 PHP 中繼承使用 extend 來聲明
class Another extends Something {
var $y;
function setY($v) {
// Methods start in lowercase then use lowercase to seperate
// words in the method name example getValueOfArea()
$this
>y=$v;
}
function getY() {
return $this
>y;
}
}
?>
這樣類
Another
的對象擁有父類的所用成員變量及方法函數
再加上自己的成員變量及成員函數
如
$obj
=new Another;
$obj
>setX(
);
$obj
>setY(
);
多重繼承不被支持
所以你不能讓一個類繼承多個類
在繼承類中你可以重新定義來重定義方法
如果我們在
Another
重新定義 getX
那麼我們不再能存取
Something
中的成員函數 getX
同樣
如果我們在繼承類中聲明一個和父類同名的成員變量
那麼繼承類的變量將隱藏父類的同名變量
你可以定義一個類的構造函數
構造函數是和類同名的成員函數
在你創建類的對象時被調用
class Something {
var $x;
function Something($y) {
$this
>x=$y;
}
function setX($v) {
$this
>x=$v;
}
function getX() {
return $this
>x;
}
}
?>
所以可以用如下方法創建對象
$obj=new Something(
);
構造函數自動賦值
給成員變量 x
構造函數和成員函數都是普通的PHP函數
所以你可以使用缺省參數
function Something($x=
$y=
)
然後:
$obj=new Something(); // x=
and y=
$obj=new Something(
); // x=
and y=
$obj=new Something(
); // x=
and y=
缺省參數的定義方法和 C++ 一樣
因此你不能傳一個值給 Y 但讓 X 取缺省值
實參的傳遞是從左到右
當沒有更多的實參時函數將使用缺省參數
只有當繼承類的構造函數被調用後
繼承類的對象才被創建
父類的構造函數沒有被調用
這是PHP不同其他面向對象語言的特點
因為構造函數調用鏈是面向對象編程的特點
如果你想調用基類的構造函數
你不得不在繼承類的構造函數中顯式調用它
這樣它能工作是因為在繼承類中父類的方法全部可用
function Another() {
$this
>y=
;
$this
>Something(); //explicit call to base class constructor
}
?>
在面向對象編程中一種好的機制是使用抽象類
抽象類是一種不能實例化而是用來給繼承類定義界面的類
設計師經常使用抽象類來強制程序員只能從特定的基類來繼承
所以就能確定新類有所需的功能
但在PHP中沒有標准的辦法做到這一點
不過
如果你在定義基類是需要這個特點
可以通過在構造函數中調用
die
這樣你就可以確保它不能實例化
現在定義抽象類的函數並在每個函數中調用
die
如果在繼承類中程序員不想重定義而直接調用基類的函數
將會產生一個錯誤
此外
你需要確信因為PHP沒有類型
有些對象是從基類繼承而來的繼承類創建的
因此增加一個方法在基類來辨別類(返回
一些標識
)並驗證這一點
當你收到一個對象作為參數派上用場
但對於一個惡棍程序沒用辦法
因為他可以在繼承類中重定義此函數
通常這種辦法只對懶惰的程序員奏效
當然
最好的辦法是防止程序接觸到基類的代碼只提供界面
重載在PHP中不被支持
在面向對象編程中你可以通過定義不同參數種類和多少來重載一個同名成員函數
PHP是一種松散的類型語言
所以參數類型重載是沒有用的
同樣參數個數不同的辦法重載也不能工作
有時候
在面向對象編程中重載構造函數很有用
所以你能以不同的方式創建不同的對象(通過傳遞不同的參數個數)
一個小巧門可以做到這一點
class Myclass {
function Myclass() {
$name=
Myclass
func_num_args();
$this
>$name();
//Note that $this
>$name() is usually wrong but here
//$name is a string with the name of the method to call
}
function Myclass
($x) {
code;
}
function Myclass
($x
$y) {
code;
}
}
?>
通過這種辦法可以部分達到重載的目的
$obj
=new Myclass(
); //Will call Myclass
$obj
=new Myclass(
); //Will call Myclass
多態性 多態性被定義為當在運行時刻一個對象作為參數傳遞時
對象能決定調用那個方法的能力
例如
用一個類定義了方法
draw
繼承類重定義
draw
的行為來畫圓或正方形
這樣你就有一個參數為 x 的函數
在函數裡可以調用$x
>draw()
如果支持多態性
那麼
draw
方法的調用就取決於對象 x 的類型
多態性在PHP中很自然被支持(想一想這種情況在C++編譯器中如果編譯
那一個方法被調用?然而你不知道對象的類型是什麼
當然現在不是這種情況)
幸好PHP支持多態性
function niceDrawing($x) {
//Supose this is a method of the class Board
$x
>draw();
}
$obj=new Circle(
);
$obj
=new Rectangle(
);
$board
>niceDrawing($obj); //will call the draw method of Circle
$board
>niceDrawing($obj
); //will call the draw method of Rectangle
?>
PHP的面向對象編程 純對象論者認為PHP不是真正的面向對象語言
這是對的
PHP是一種混合語言
你可以用面向對象或傳統結構編程的方法來使用它
對於大型工程
然而你可能或需要使用純面向對象方法來定義類
並在你的工程中只使用對象和類
越來越大的工程通過使用面向對象的方法會獲得益處
面向對象工程非常容易維持
容易理解並且重用
這是軟件工程的基本
使用這些概念在網站設計中是未來成功的關鍵
PHP中的高級面向對象技術 在回顧面向對象的基本概念之後
我將介紹一些更高級的技術
串行化 PHP並不支持持久性對象
在面向對象語言中持久性對象是一些經過應用程序多次調用仍然保持其狀態和功能的對象
這意味著有一種能保存對象到文件或數據庫中然後重新裝載對象
這種機制稱之為串行化
PHP 有一個串行化函數
可以在對象中調用
串行化函數返回一個字符串代表這個對象
然後串行化函數保存的是成員數據而不是成員函數
在PHP
中
如果你串行化一個對象到字符串 $s
然後刪除此對象
再反串行化對象到 $obj
你仍然可以調用對象的方法函數
但我不推薦這種方法
這因為(a)這種功能在將來不一定支持(b)這導致一種幻象
如果你保存串行化對象到磁盤並退出程序
將來重新運行此腳本時你不能反串行化此對象並希望對象的方法函數仍有效
因為串行化出來的字符串並沒有表示任何成員函數
最後
串行化保存對象的成員變量在PHP中非常有用
僅僅如此
(你可以串行化聯合數組和數組到磁盤裡)
例子:
$obj=new Classfoo();
$str=serialize($obj);
// Save $str to disk
//
some months later
//Load str from disk
$obj
=unserialize($str)
?>
上例中
你可以恢復成員變量而沒有成員函數(根據文檔)
這導致 $obj
>x 是
From:http://tw.wingwit.com/Article/program/PHP/201311/20815.html