首頁  >  文章  >  後端開發  >  php中建構函式的繼承分析

php中建構函式的繼承分析

黄舟
黄舟原創
2017-07-02 10:02:051668瀏覽

建構子用法

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&#39;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 &#39;水果&#39;.$name.&#39;创建了&#39;;
}
}
 
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 &#39;this is base1 construct&#39;;
  }
}
class class1 extends base1
{
  function class1()
  {
$this->base1();
echo &#39;this is class1 construct&#39;;
  }
}
$c1 = new class1;

PHP5.x 版本:

PHP5.0 以上版本對類別的功能進行了很大的擴充。類別的建構子統一命名為construct()。
子類別的建構函式名稱也是construct()(也是廢話)。
在子類別裡父類別的建構子會不會執行,分兩種情況:
1,如子類別不定義建構函式construct(),則父類別的建構子預設會被繼承下來,且會自動執行。
2,如子類別定義了建構子 construct(),因為建構函式名稱也是construct(),所以子類別的建構子其實是覆蓋(override)了父類別的建構子。這時執行的是該子類別的建構子。
   這時如果要在子類別裡執行父類別的建構函數,必須執行類似以下語句:

parent::construct();

#例如:

class base2
{
  function construct()
  {
echo &#39;this is base2 construct&#39;;
  }
  function destruct()
  {
  }
}
class class2 extends base2
{
  function construct()
  {
parent::construct();
echo &#39;this is class2 construct&#39;;
  }
}

注意 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 &#39;this is class2 construct&#39;;
  }
  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(&#39;set in constructor&#39;);
$bar1->echoName();
$globalref[0]->echoName();
/* &#36755;&#20986;&#65306;
set in constructor
set in constructor
set in constructor */
$bar2 =& new Foo(&#39;set in constructor&#39;);
$bar2->echoName();
$globalref[1]->echoName();
/* &#36755;&#20986;&#65306;
set in constructor
set in constructor
set in constructor */
?>

以上是php中建構函式的繼承分析的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn