首頁  >  文章  >  php教程  >  1.2魔術方法和延遲靜態綁定

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

WBOY
WBOY原創
2016-08-23 09:03:381097瀏覽

一.魔術方法:

  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{<br>}<br>class B extends A{<br>    public static function out(){<br>        return new self();<br>    }<br>}<br>class C extends A{<br>    public static function out(){<br>        return new self();<br>    }<br>}<br>var_dump(B::out());//结果是object(B)#1 (0) { }<br>var_dump(C::out());//结果是object(C)#1 (0) { }<br>然后我们将子类中相同的代码抽取到父类class A中,变成:
class A{<br>    public static function out(){<br>        return new self();<br>    }<br>}<br>class B extends A{<br>}<br>class C extends A{<br>}<br>var_dump(B::out());//结果是object(A)#1 (0) { }<br>var_dump(C::out());//结果是object(A)#1 (0) { }<br>这个结果显然不是我们想要的,这里的问题主要是因为self指代的是它所在的类.这里self在类A里面,所以返回的永远是类A的对象,<br>而我们想要的是让out()方法返回调用它的类的对象而不是它所在的类的对象.怎么办?<br>此时我们马上可以想到$this可以代表调用它的对象,但是out()是一个静态方法,里面是不能出现$this的,怎么办?<br>用static.它也代表调用它的对象如:
class A{<br>    public static function out(){<br>        return new static();<br>    }<br>}<br>class B extends A{<br>}<br>class C extends A{<br>}<br>var_dump(B::out());//结果是object(B)#1 (0) { }<br>var_dump(C::out());//结果是object(C)#1 (0) { }<br>这样就好了.这就是延迟静态绑定.<br><br>在看下面的例子:

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

首先物件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

 


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