建構函式用法
HP 5 允行開發人員在一個類中定義一個方法作為建構函式。具有建構函式的類會在每次建立新對象時先調用此方法,所以非常適合在使用對象之前做一些初始化工作。
Note: 如果子類中定義了建構函式則不會隱式調用其父類的建構函式。要執行父類的建構函式,需要在子類的建構函式中調用 parent::construct()。如果子類沒有定義建構函式則會如同一個普通的類方法一樣從父類繼承(假如沒有被定義為 private 的話)。
Example #1 使用新標準的建構函式
<?phpclass BaseClass { function construct() { print "In BaseClass constructorn"; }}class SubClass extends BaseClass { function construct() { parent::construct(); print "In SubClass constructorn"; }}class OtherSubClass extends BaseClass { // inherits BaseClass's constructor}// In BaseClass constructor$obj = new BaseClass();// In BaseClass constructor// In SubClass constructor$obj = new SubClass();// In BaseClass constructor$obj = new OtherSubClass();?>
為了實現向後相容性,如果 PHP 5 在類中找不到 construct() 函數並且也沒有從父類繼承一個的話,它就會嘗試尋找舊式的建構函式,也就是和類同名的函數。因此唯一會產生相容性問題的情況是:類中已有一個名為 construct() 的方法卻被用於其它用途時。
與其它方法不同,當 construct() 被與父類 construct() 具有不同參數的方法覆蓋時,PHP 不會產生一個 E_STRICT 錯誤資訊。
自 PHP 5.3.3 起,在命名空間中,與類名同名的方法不再作為建構函式。這一改變不影響不在命名空間中的類。
Example #2 Constructors in namespaced classes
<?phpnamespace Foo;class Bar { public function Bar() { // treated as constructor in PHP 5.3.0-5.3.2 // treated as regular method as of PHP 5.3.3 }}?>
建對象的時候賦初值。
1. //建立一個人類 2. 3. 0class Person 4. 0{ 5. //下面是人的成員屬性 6. var $name; //人的名子 7. var $sex; //人的性別 8. var $age; //人的年齡 9. //定義一個構造方法參數為姓名$name、性別$sex和年齡$age 10. function construct($name, $sex, $age) 11. { 12. //通過構造方法傳進來的$name給成員屬性$this->name賦初使值 13. $this->name=$name; 14. //通過構造方法傳進來的$sex給成員屬性$this->sex賦初使值 15. $this->sex=$sex; 16. //通過構造方法傳進來的$age給成員屬性$this->age賦初使值 17. $this->age=$age; 18. } 19. //這個人的說話方法 20. function say() 21. { 22. echo "我的名子叫:".$this->name." 性別:".$this->sex." 我的年齡是:".$this->age."<br>"; 23. } 24. } 25. //通過構造方法建立3個對象$p1、p2、$p3,分別傳入三個不同的實參為姓名、性別和年齡 26. $p1=new Person("張三","男", 20); 27. $p2=new Person("李四","女", 30); 28. $p3=new Person("王五","男", 40); 29. //下面訪問$p1對象中的說話方法 30. $p1->say(); 31. //下面訪問$p2對象中的說話方法 32. $p2->say(); 33. //下面訪問$p3對象中的說話方法 34. $p3->say();
輸出結果為:
我的名子叫:張三性別:男我的年齡是:20
我的名子叫:李四性別:女我的年齡是:30
我的名子叫:王五性別:男我的年齡是:40
建構函式的繼承問題
先來看一個簡單的例子:
<?phpclass Fruit {public function construct($name){echo '水果'.$name.'建立了';}} class Apple extends Fruit {public function construct($name){parent::construct($name);}} $apple = new Apple("蘋果"); // 輸出 水果蘋果建立了?>
建構函式的繼承節省的是代碼的重寫,而不是方法的聲明,也就是說,在父類中聲明的建構函式必須再在子類中聲明一次,其實,這也是一個重寫的過程。
PHP的建構函式繼承必須滿足以下條件:
當父類有建構函式的聲明時,子類也必須有聲明,否則會出錯。
在執行父類的建構函式時,必須在子類中引用parent關鍵字。
如果父類有建構函式,而且子類沒有建構函式,那麼在子類執行個體化時確實會執行父類建構函式。例如,假設Employee類有如下建構函式:
function construct($name){$this->setName($name);}然後執行個體化CEO類,獲得其name成員:$ceo= new CEO("Gonn");echo $ceo->getName();將得到如下結果:My name is Gonn
但是,如果子類也有建構函式,那麼當子類執行個體化時,不論父類是否有建構函式,都會執行子類自己的建構函式。例如,假設除了Employee類包含上述建構函式外,CEO類也包含如下建構函式:
function construct(){echo "CEO object created!";}
再來執行個體化CEO類,以同樣的方式執行getName(),這次將得到不同的輸出:
CEO object created!
My name is Gonn
當遇到parent::construct()時,PHP開始沿著父類向上搜尋合適的建構函式。因為在Executive中沒有找到,所以繼續搜尋知道Employee類,在這裡找到了合適的建構函式。如果PHP在Employee類中找到建構函式,就會執行這個建構函式。如果希望既執行Employee建構函式,又執行Executive建構函式,則需要在Executive建構函式中調用parent::construct()。
此外,還可以選擇另一種方式來引用父類的建構函式。例如,假設建立新的CEO對象時,Employee和Executive的建構函式都要執行。如上述,可以在CEO的建構函式中顯示地引用這些建構函式,如下:
function construct($name){Employee::constrcut($name);Executive::construct();echo "CEO object created!";}
不同php版本中建構函式繼承
建構函式中的引用
PHP 4.x 的建構函式名與類名相同。
子類的建構函式名與子類名相同(廢話)。
在子類裡父類的建構函式不會自動執行。
要在子類裡執行父類的建構函式,必須執行類似以下語句:
$this->[父類的建構函式名()]
例如:
class base1{ function base1() {echo 'this is base1 construct'; }}class class1 extends base1{ function class1() {$this->base1();echo 'this is class1 construct'; }}$c1 = new class1;
PHP5.x 版本:
PHP5.0 以上版本對類的功能進行了很大的擴充。類的建構函式統一命名為construct()。
子類的建構函式名也是construct()(也是廢話)。
在子類裡父類的建構函式會不會執行,分兩種情況:
1,如子類不定義建構函式 construct(),則父類的建構函式預設會被繼承下來,且會自動執行。
2,如子類定義了建構函式 construct(),因為建構函式名也是construct(),所以子類的建構函式實際上是覆蓋(override)了父類的建構函式。這時執行的是該子類的建構函式。
這時如果要在子類裡執行父類的建構函式,必須執行類似以下語句:
parent::construct();
例如:
class base2{ function construct() {echo 'this is base2 construct'; } function destruct() { }}class class2 extends base2{ function construct() {parent::construct();echo 'this is class2 construct'; }}
注意 parent::construct(); 語句不一定必須放在子類的建構函式中。放在子類的建構函式中僅僅保證了其在子類被執行個體化時自動執行。
PHP4.0 和 5.0 類建構函式的相容問題:
在 PHP5.0 以上版本裡,還相容了 4.0 版本的建構函式的定義規則。如果同時定義了4.0的建構函式和 construct()函數,則construct() 函數優先。
為了使類代碼同時相容 PHP4.0 和 5.0,可以採取以下的方式:
class class3{ function construct() //for PHP5.0 {echo 'this is class2 construct'; } function class3() //for PHP4.0 {$this->construct(); }}$c3 = new class3;
php建構函式中的引用的內容。
<?phpclass Foo { function Foo($name) { global $globalref; $globalref[] = &$this; $this->setName($name); $this->echoName(); } function echoName() { echo "<br />",$this->name; } function setName($name) { $this->name = $name; }}?>
下面來檢查一下用拷貝運算子 = 建立的 $bar1 和用引用運算子 =& 建立的 $bar2 有沒有區別...
copy to clipboard
顯然沒有區別,但實際上有一個非常重要的區別:$bar1 和 $globalref[0] 並沒有被引用,它們不是同一個變數。這是因為“new”預設並不返回引用,而返回一個拷貝。
<?php$bar1 = new Foo('set in constructor');$bar1->echoName();$globalref[0]->echoName();/* 输出:set in constructorset in constructorset in constructor */$bar2 =& new Foo('set in constructor');$bar2->echoName();$globalref[1]->echoName();/* 输出:set in constructorset in constructorset in constructor */?>