程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 網頁編程 >> PHP編程 >> 關於PHP編程 >> 1.2魔術方法和延遲靜態綁定,1.2魔術延遲靜態

1.2魔術方法和延遲靜態綁定,1.2魔術延遲靜態

編輯:關於PHP編程

1.2魔術方法和延遲靜態綁定,1.2魔術延遲靜態


一.魔術方法:

  1.__get,__set

  __get:獲取一個不可訪問的屬性時觸發(不可訪問指屬性不存在,或者沒有訪問權限)

  __set:為一個不可訪問的屬性賦值的時候觸發

  2.__isset,__unset

  __isset:當用isset()函數判斷一個不可訪問的屬性時觸發

  __unset:當用unset()函數操作一個不可訪問的屬性時觸發

  3.__call,__callStatic

  __call:當調用一個不可訪問的方法時觸發

  __callStatic:當調用一個不可訪問的靜態方法時觸發

  4.__construct,__destruct

  __construct:初始化一個對象時觸發

  __destruct:對象銷毀,或者腳本執行完時觸發

  5.__autoload

  __autoload:當使用一個不可訪問的類時觸發

  6.__clone

  __clone:對象被克隆時觸發

  7.__sleep,__wakeup

  __sleep:使用serialize時觸發

  __wakeup:使用unserialize時觸發

  8.__toString,__invoke

  __toString:當一個對象被當做字符串來操作時觸發,如$obj是一個對象,echo $obj,就會觸發__toString

  __invoke:當一個對象被當做函數來使用時觸發,如$obj是一個對象,$obj()就會觸發__invoke

 

二.延遲靜態綁定

  拋開概念看例子理解就好:

  首先延遲靜態綁定是怎麼出現的?看下面例子:

class A{
}
class B extends A{
public static function out(){
return new self();
}
}
class C extends A{
public static function out(){
return new self();
}
}
var_dump(B::out());//結果是object(B)#1 (0) { }
var_dump(C::out());//結果是object(C)#1 (0) { }
然後我們將子類中相同的代碼抽取到父類class A中,變成:
class A{
public static function out(){
return new self();
}
}
class B extends A{
}
class C extends A{
}
var_dump(B::out());//結果是object(A)#1 (0) { }
var_dump(C::out());//結果是object(A)#1 (0) { }
這個結果顯然不是我們想要的,這裡的問題主要是因為self指代的是它所在的類.這裡self在類A裡面,所以返回的永遠是類A的對象,
而我們想要的是讓out()方法返回調用它的類的對象而不是它所在的類的對象.怎麼辦?
此時我們馬上可以想到$this可以代表調用它的對象,但是out()是一個靜態方法,裡面是不能出現$this的,怎麼辦?
用static.它也代表調用它的對象如:
class A{
public static function out(){
return new static();
}
}
class B extends A{
}
class C extends A{
}
var_dump(B::out());//結果是object(B)#1 (0) { }
var_dump(C::out());//結果是object(C)#1 (0) { }
這樣就好了.這就是延遲靜態綁定.

在看下面的例子:

為什麼是這個結果呢?我們分析一下:

首先對象c調用get()方法,但是在類C中沒有找到,於是它去類B中找,找到了.然後執行這個get方法,

先執行A::foo(); 類A會直接調用它自己的foo(),輸出`fooA`,然後調用out,很明顯這裡調用static::out()的就是類A,所以輸出的類名也是A.(這裡側重於類A)

再執行parent::foo(); parent表示父類,這裡會去執行類A中的foo(),輸出`fooA`,然後執行static::out(),此時調用這個static的不是類A,而是類C,因為parent代表的是父類,但不代表具體哪一個類(這裡側重於父類中的方法,而不管父類是誰).

然後執行self::foo(); self表示它所在的類(類B),它先執行foo(),沒有再去父類中找,所以輸出`fooA`,然後執行static::out(),同理這裡使用static的不是類A,而是類C,self雖然代表類B,但是self不能代表一個具體的類.

簡單點說:對象c開始執行get()-->A::foo();此時鏈子就斷了,變成由類A直接去調用foo()了,和對象c沒關系了.這裡的static當然指的是類A.

     接著,對象c-->parent::foo()-->類A中的foo()-->static::out(),這裡的parent說白了就是一個指向作用,即執行誰的foo()方法.所以可以理解為對象c調用類A中的foo方法.那麼foo中的static代表類C

     最後,對象c-->self::foo()-->類A中的foo()-->static::out(),同上,這裡的self也是一個指向的作用,但是最終還是到了類A.可以理解為對象c調用類A中的foo方法.那麼foo中的static代表類C

 




  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved