注意:高階oop特性只在php5及以上版本支援(抽象類、命名空間需要5.3及以上)
在php5中,將所有對物件都看作引用,而不是值。那麼如何建立物件的副本呢?答案就是轉殖物件。
語法:destinationobject = clone targetobject ;
可以在乙個類裡面定義乙個__clone()方法來調整轉殖行為。此方法將在轉殖操作期間執行。
<?php
class employee
function settiecolor($tiecolor)
function getid()
function gettiecolor()
function __clone()
} $emp1 = new employee();
$emp1->setid('123');
$emp1->settiecolor('red');
$emp2 = clone $emp1;
echo $emp1->getid().'
'; echo $emp1->gettiecolor().'
'; echo $emp2->getid().'
'; echo $emp2->gettiecolor();
?>
執行結果:
123red
123blue
<?php
class employee
class executive extends employee
?>
若子類沒有建構函式,父類有建構函式,則子類在例項化時呼叫父類的建構函式;
如子類有建構函式,則不論父類是否有建構函式,都呼叫子類的建構函式;當然,如果想呼叫父類的建構函式,也是有辦法的;
比如a,b,c三個類的關係是:b繼承a,c繼承b;他們三者建構函式情況是:a有建構函式,b沒有建構函式,c有建構函式,此時三者的建構函式互不呼叫。
當想在c中呼叫父類(b&c)的建構函式時,需要在c的建構函式中加上這句話:parent::__construct();,此時,ph開始沿著父類向上搜尋合適的建構函式,就會找到a的構造
函式並呼叫,如果b中也有合適的建構函式的話,就不會呼叫a的建構函式,而是呼叫b的建構函式。即,c會呼叫找到的第乙個合適的父類建構函式。
此時,如果c還
想呼叫a的建構函式,只需要在b的建構函式中呼叫a的建構函式;還有一種辦法,就是在c的建構函式中寫:b::__construct();c::__construct();。
看下面這段**:
<?php
class a
} class b extends a
echo b::watchtv();
?>
結果永遠是
watching footboll
因為self關鍵字會在編譯時而非執行時確定其作用域。
如果想執行時確定靜態屬性的作用域,就可以使用static關鍵字。為此,重新寫watchtv方法:
public static function watchtv()
介面使一些未實現的方法定義和常量的集合,相當於一種類藍本。介面只定義了類能做什麼,而不涉及實現細節。
之所以不提供具體實現細節,是因為不同的實體可能需要用不同的方式來實現公共的方法定義。
注意:介面不定義類成員,類成員完全交給實現類來定義。
inte***ce iinte***cename
*通常,在介面名前面加上字母i來進行表示,一邊更容易辨認。
當類通過implements關鍵字實現了implements介面後,就完成了乙個契約。介面中的所有方法都必須事先,否則會出現致命錯誤。
下面是實現上述介面的一般語法:
class class_name implements inte***cename
function methodnamen() }
<?php
inte***ce ren1
inte***ce ren2 extends ren1
inte***ce ren3
inte***ce ren4
class ren5
} class ren extends ren5 implements ren2,ren3,ren4
function shuohua2()
function shuohua3()
function shuohua4()
function shuohua5()
function shuohua6()
} $r = new ren();
echo ren::xingming.'
'; $r->shuohua1();echo '
'; $r->shuohua2();echo '
'; $r->shuohua3();echo '
'; $r->shuohua4();echo '
'; $r->shuohua5();echo '
'; $r->shuohua6();echo '
'; $r->shuohua7();
?>
樣例輸出是:
daniel
1111
2222
3333
4444
5555
6666
7777
注意:介面可以多繼承,而類是不可以的。
抽象類是無法例項化的類,抽象類將由可例項化的類繼承,後者稱為具體類(concrete class)。
抽象裡可以完全實現、部分實現或則根本不實現。
abstract class class_name
不能例項化乙個抽象類,否則會出現致命的錯誤。
為了確保抽象類的一致性,所有派生類都必須實現從該抽象類繼承的所有抽象方法,否則導致致命錯誤。
1、如果要建立乙個模型,這個模型將由一些緊密相關的物件採用,就可以使用抽象類。如果要建立將由一些不相關物件採用的功能,就使用介面;(抽象類的類特性)
2、如果必須從多個**繼承行為,就使用介面;(因為介面可以多繼承)
3、如果知道所有類都會共享乙個公共的行為實現,就是用抽象類,並在其中實現該行為。在介面中無法實現行為。(因為抽象類可以部分實現)
命名空間可以根據上下文劃分各種類和庫,幫助你更為有效的管理**庫。
隨著不斷建立類庫並使用類庫,最後可能出現這樣一種情況,兩種類庫使用了相同的類名,而這會導致不可預期的應用結果。命名空間就用來解決這個問題。
下面通過乙個例子來講解:
class clean }
這是個健康**,你還需要通過乙個不文明語言過濾器來過濾使用者提供的所有資料。你建立了乙個datecleaner.inc.php的php類庫,這個類庫中也有乙個類名為clean的類,這個類中包含乙個函式removeprofanity(),它負責把不文明的語言,替換**類能接受的語法:
<?php
class removeprofanity($text)
?>
你迫不及待的在同一指令碼下使用這兩個類庫:
require "datacleaner.inc.php";
require "libary.inc.php";
然後做一些修改來使用這個不文明過濾器,你將會的到乙個致命的錯誤。
我們只要為各個類指定乙個命名空間,就可以解決這個問題。
開啟libaray.inc.php,並把下面這行**放在檔案的最前面:
namespace com\wjgilmore\libary;
類似的,開啟datacleaner.inc.php,把下面這行**也放在檔案的最前面
namespace com\thirdparty\datacleaner;
然後就可以使用這兩個clean類,而不用擔心命名衝突。
為此,可以例項化各個類,但要在類的前面增加命名空間作為字首:
<?php
namespace datacleaner;
class clean }
?>
<?php
namespace library;
class clean }
?>
<?php
require "library.inc.php";
require "datacleaner.inc.php";
use datacleaner as dc;
use library as lib;
//例項化library的clean類
$filter = new lib\clean();
//例項化datafilters的clean類
$profanity = new dc\clean();
//建立乙個書名
$title = "the idiotic sun alse rises";
//在過濾前輸出書名
echo $title.'
'; //移除書名中的「髒話」
$title = $profanity->removeprofanity($title);
echo "title after dc:".$title.'
'; //移除空格,並使用名為首字母大寫
$title = $filter->filtertitle($title);
echo "title after lib:".$title;
?>
方法過載
操作符過載
多重繼承
PHP的高階OOP技術
在看過基本的oop概念後,我就可以向你展示更高階的技術 序列化 serializing php不支援永久物件,在oop中永久物件是可以在多個應用的引用中保持狀態和功能的物件,這意味著擁有將物件儲存到乙個檔案或資料庫中的能力,而且可以在以後裝入物件。這就是所謂的序列化機制。php 擁有序列化方法,它可...
PHP的高階OOP技術
php的高階oop技術 在看過基本的oop概念後,我就可以向你展示更高階的技術 序列化 serializing php不支援永久物件,在oop中永久物件是可以在多個應用的引用中保持狀態和功能的物件,這意味著擁 有將物件儲存到乙個檔案或資料庫中的能力,而且可以在以後裝入物件。這就是所謂的序列化機制。p...
PHP高階OOP技術演示
序列化 serializing php不支援永久物件,在oop中永久物件是可以在多個應用的引用中保持狀態和功能的物件,這意味著擁有將物件儲存到乙個檔案或資料庫中的能力,而 且可以在以後裝入物件。這就是所謂的序列化機制。php 擁有序列化方法,它可以通過物件進行呼叫,序列化方法可以返回物件的字串表示。...