萬盛學電腦網

 萬盛學電腦網 >> 網絡編程 >> php編程 >> PHP構造函數的繼承分析

PHP構造函數的繼承分析

在php中PHP構造函數是一個提高工作性能的不作做法了,它可以實現自動構造與自動處理一些變量或執行指定函數了,下面給大家全部的介紹了構造函數的用法。

構造函數用法

HP 5 允行開發者在一個類中定義一個方法作為構造函數。具有構造函數的類會在每次創建新對象時先調用此方法,所以非常適合在使用對象之前做一些初始化工作。

Note: 如果子類中定義了構造函數則不會隱式調用其父類的構造函數。要執行父類的構造函數,需要在子類的構造函數中調用 parent::__construct()。如果子類沒有定義構造函數則會如同一個普通的類方法一樣從父類繼承(假如沒有被定義為 private 的話)。
Example #1 使用新標准的構造函數

 代碼如下 復制代碼

<?php
class 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

 代碼如下 復制代碼

<?php
namespace 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

構造函數的繼承問題

先來看一個簡單的例子:

 代碼如下 復制代碼


<?php

class 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構造函數中的引用的內容。

 代碼如下 復制代碼 <?php
class 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();
/* &#36755;&#20986;&#65306;
set in constructor
set in constructor
set in constructor */
$bar2 =& new Foo('set in constructor');
$bar2->echoName();
$globalref[1]->echoName();
/* &#36755;&#20986;&#65306;
set in constructor
set in constructor
set in constructor */
?>

 

copyright © 萬盛學電腦網 all rights reserved