PHP 類別的變數與成員,及其繼承、存取與重寫時要注意的問題

WBOY
發布: 2016-07-25 09:03:11
原創
921 人瀏覽過
  1. class Myclass{

  2. public $prop = 123;
  3. }
  4. $obj = new Myclass();

  5. ?>
複製程式碼

類別的成員屬性(屬性的稱呼相對於「方法」而言)包括類別常數和類別變量,其中類別常數在定義時不可為空,類別的屬性在定義時如果被賦值,只能使用標量和數組,並且不能是表達式,因為類別屬性在編譯期被初始化,PHP 在編譯期不執行表達式。

1、成員的存取控制public:可以繼承,可以在類別的方法之外被存取 , 如 $obj->prop; protected:可以繼承,不可以在類別的方法之外被訪問 private:不可以繼承,不可以在類別的方法之外存取

PHP 4 使用 var 來聲明類別的屬性,在PHP5之後不再使用,PHP5.3之前使用被警告,PHP5.3之後可以用在 public 之前或單獨使用作為 public 的別名。

這三個存取控制關鍵字也可以修飾建構函數,當private 和protected 修飾類別的建構子時,你只能透過一個publice static 的靜態方法來呼叫建構子以實例化對象,因為夠在函數無法在類別之外被存取了,例如,單例類別的實作:

  1. class Singleton {

  2. private static $instance=null;
  3. public $k = 88;
  4. private function __construct(){
  5. }

  6. public static function getInstance(){

  7. if(self::$instance= =null){
  8. self::$instance = new self();
  9. }
  10. return self::$instance;

  11. }
  12. public function __clone(){ //pretend clone oprationg

  13. throw('Singleton class can not be cloned');
  14. return self::getInstance();
  15. }
  16. }>} p>
  17. //new Singleton(); // Error

  18. $in = Singleton::getInstance();
  19. ?>
複製程式碼

2、繼承禁止: final 關鍵字,僅用於修飾類別或類別的方法

如果一個類別被 final 修飾,這個類別不能被繼承,如果一個方法被final 修飾,則這個方法不能被子類別重寫(override)。

  1. class Myclass{
  2. public $prop = 123;
  3. final public static function methodA(){///不可繼承的,公開的靜態方法
  4. return 'this is a final method';
  5. }
  6. }
  7. ?>
複製代碼

3、抽象類別和抽象方法:abstract 僅用於類別和方法,抽象類別不能直接用於實例化物件只能用於產生子類

  1. abstract class Myclass{
  2. public $prop = 123;
  3. abstract public function methodA() //抽象;方法沒有實作函數體
  4. }
  5. ?>
複製程式碼

4、類別的常數及其存取

4、類別的常數及其存取
    4、類別的常數及其存取
  1. 4、類別的常數>
  2. :類別的常數不能使用存取限制修飾符,他是public 的,可繼承,可以被子類別重寫,存取類別的常數必須使用雙冒號:: ,可以使用類別名稱或類別的實例來存取。
  3. class Myclass{

  4. public $prop = 123;
  5. const x =999;
  6. public static function methodA(){

  7. return 'this is a final method';
  8. }
  9. public function getConst(){

  10. return self::x; //或$this::x;
  11. }
}

$instance = new Myclass();

echo Myclass::x;

echo $instance::x;
echo $instance->getConst();?> 複製程式碼

類別的常數是一個值,在程式碼編譯期常數名被替換為對應的值,在運行期不可修改,因此,類別的常數是與類別本身相關,在實例化物件之前就已經存在了,因此類別的常數可以直接使用類別名稱存取。

  1. class P{

  2. const m = 100;
  3. const n = p = :: m;
  4. }
  5. class S extends P{

  6. const m=200;
  7. public function getPConst(){
  8. return parent::n;
  9. }
  10. }
  11. $p = new P();

  12. $s = new S();
  13. echo $p::n; //100
  14. echo $s::n; //200 此常數名稱是繼承自父類,在編譯期取self::m 的值替換,注意區別類別的方法使用self::m
  15. echo $s->getPConst(); //100

  16. ?>
複製程式碼

5、類別的靜態成員及訪問

static 可以修飾類別的屬性及方法,被static 修飾的成員屬於類別而不屬於類別的實例,靜態成員必須使用類別名稱加雙冒號:: 來訪問, 因為在實例化物件之前靜態成員就存在了,因此,在靜態方法內,禁止使用指向實例本身的偽變量$this(或習慣上稱為$this 指針) ,可以使用關鍵字self 代替類名(相當於類的魔術常數__CLASS__)。

static 不能用來修飾 類別的建構函數,也不能用來修飾介面宣告的方法。

  1. class Myclass{

  2. public static $x = 99;
  3. public function getX(){

  4. return self::$x;
  5. }
  6. }
  7. echo Myclass::x; //99

  8. ? >
複製程式碼

靜態成員可以使用存取控制關鍵字修飾,可以被繼承和重寫,需要注意的是,如果一個子類別繼承了父類別的靜態方法(沒有重寫該方法),那麼子類別呼叫的實際上是父類別的靜態方法。因為靜態成員持有者是類別不是對象,所以類別的多個實例是共享同一個靜態屬性的,在一個實例中修改靜態屬性會影響到另一個實例中的靜態屬性:

  1. class A{

  2. public static $a1 = 11;

  3. public $a2 = 22;
  4. public static function showStatic(){

  5. return self::$a1;
  6. }
  7. public function getStatic(){

  8. return self::$a1;
  9. }
  10. public function getClassStatic(){

  11. $className = get_called_class();
  12. return
  13. return
  14. $className::$a1;
  15. }
  16. public function getProp(){

  17. return $this->a2;
  18. }
  19. }
  20. class B extends A{

  21. public static $a1 = 88;
  22. public $a2 = 99;
  23. }
  24. $obj1 = new A() ;

  25. $obj2 = new B();
  26. echo A::showStatic(); //11

  27. echo $obj1->getStatic(); //11
  28. echo $obj1->getClassStatic(); //11
  29. echo $obj1->getProp(); //22
  30. echo B::showStatic(); //11 呼叫的是父類別的方法,存取父類別的靜態成員

  31. echo $obj2->getStatic(); //11 呼叫的是父類別的方法,方法中的self 指向持有該靜態方法的類別
  32. echo $obj2->getClassStatic(); //88
  33. echo $obj2->getProp(); //99
  34. ?>
複製程式碼

後期靜態綁定:為了避免子類別重寫靜態屬性後,使用繼承來的方法仍然存取父類別的靜態屬性, PHP5.3 增加了一個新的語法:後期靜態綁定,使用static 關鍵字取代self 關鍵字,使得static 指向與get_called_class() 傳回的相同的類,即當前呼叫該靜態方法的物件所屬的類,該關鍵字對於靜態方法的存取同樣有效。

  1. public function getClassStatic(){

  2. $className = get_called_class() }
  3. //可以寫成:

  4. public function getClassStatic(){
  5. return static::$a1;
  6. }
  7. //用於靜態方法

  8. //A類別中:
  9. public static function testStatic(){
  10. echo "

    testStatic of A

    " ;
  11. }
  12. public function callStatic(){

  13. static::testStatic();
  14. }
  15. //B類中:

  16. public static function testStatic(){
  17. echo "

    testStatic of B

    ";
  18. }
  19. //B類別繼承A類別的callStatic 方法,可以正確存取各自類別的testStatic 方法。
  20. ?>
複製程式碼

6、類別的方法中幾個指向類別或實例的關鍵字 $this->propName $this 指向類別的實例 parent::xxx parent 指向父類,可以存取父類別的靜態常數、靜態屬性(parent::$xxx) ,不能存取父類別的非靜態屬性,可以呼叫父類別的方法(不能是private 方法,無論是否靜態) self::xxx self 指向定義了目前被呼叫的方法的類,用於存取靜態成員和類別的常數 static::xxx 存取實例化了呼叫當前方法的實例的那個類,用於訪問靜態成員和累的常數,他跟 self 的差別是訪問靜態成員時採用 “後期靜態綁定”。

7、類別的繼承中的 重寫問題: 重寫的成員的存取控製程度不能被縮小,例如, public 的成員不能重寫為 protected 非靜態成員不能改寫為靜態成員,靜態成員也不能改寫為非靜態成員

8、介面中定義的方法必須是 public 類別在實作介面的方法時,這些方法也必須是 public 的,具體實作的(不​​能是 abstract )。 介面也可以定義介面常數,用法與類別常數完全一致,但是介面不可以定義非函數成員。 介面與介面之間可以繼承,介面的繼承可以是多繼承,用逗號隔開(字類別與父類別的繼承是單繼承的) 一個類別可以實現多個接口,用逗號隔開

  1. interface Ix extends Iy,Iz{
  2. public function a();
  3. }
  4. }
  5. class A implements Iy,Iz{
  6. .......
  7. }
  8. ?>
複製程式碼

9、模式約束

PHP 的函數(或類別的方法) 可以在宣告時限定參數的類型,但只能限定array 或object(class/interface) ,如果限定為string 型, PHP 會認為是限定為一個string 類別的object 參數。

如果類型被限定為某個接口,則傳入的參數必須是實作該介面的類別的實例。

在介面實作、子類別重寫父類別方法時,不能修改已經限定的參數類型。

在方法、函數呼叫時,如果傳入了與限定的參數類型不同的資料將會報錯,但是可以接受 null 參數。

  1. interface Im{

  2. public function a( classm $m);
  3. }
  4. }
  5. class A implements Im{

  6. public function a($x){ // error ,參數$x必須限定為classm 類型以符合介面的定義
  7. var_dump($x) ;
  8. }
  9. }
  10. ?>
複製程式碼


來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!