php利用反射真正實現多繼承(非接口模擬)

昨天我在寫PHP程序的時候,無心發如今PHP的::操做符很是強大,不單單是隻用在訪問parent,sel,靜態成員屬性、常量上面,其實他的功能強大了去了


php


這個符號在PHP中實際上叫作範圍解析符,這是PHP官方的解釋php.net/manual/zh/language.oop5.paamayim-nekudotayim.php。可是官方中文部分只是簡單的介紹了

訪問parent,sel,靜態成員屬性、常量的做用,而下面英文部分,可能因爲我們這些吊死對英文很差的緣故,就沒看下去了,實現上,下面還有一個強大的特性,咱們你們都沒看到。
什麼叫範圍操做符呢,可能不少人都沒有認真的去分析過,這幾個字,根據我這兩年的編程的理解,我以爲應該是定義了類中的成員屬性和成員方法的所在範圍,感受有點相似命名空間的感受。
而self::method();其實指的就是調用當前範圍裏的method方法,那parent天然指的就是父類所在範圍,這就是爲何,咱們在子類中 覆蓋父類的方法,咱們仍然能夠用parent::method()訪問的緣由。你們還要注意一點,self永遠指向的是其實聲明位置所在類自己和而 parent永遠指向的是聲明位置所在類的父類,不會受繼承上下文的影響而改變。
前面講的這些可能你們有些人已經知道了,上面說過::在PHP中叫範圍解析操做符,上面我說過了既然,parent和self都能指向一個類範圍的代名詞,那試想下,咱們能不能用類名指向某個範圍呢,答案固然是能夠的。咱們能夠這樣html

  1. class a{
  2.         public function demo(){
  3.                 echo 'abc';
  4.         }
  5. }
  6.  
  7.  
  8.  
  9.  
  10. a::demo();
不知道你們發現沒,裏面的demo方法並不靜態方法,但我卻能夠這樣訪問,那是由於a::指向的class範圍,因此能夠訪問時面的demo方法,PHP官方有這樣的示例代碼,就在上面我發的連接中,你們能夠仔細看下。

你們確定又疑惑這跟多繼承有什麼關係呢,別急,心急吃不了熱豆腐的!!!!!
其實這個範圍操做符還有一個很大的特性,就是當在類外部調用一個非靜態公共方法時,方法內部的$this指針會指向他當前運行所在對象自己(宿主對象), 當一個類實例化時,方法裏面$this永遠指向的實例化後的對象自己,爲何呢,由於這個方法是被這個對象調用執行的,因此這個對象就是他的宿主對象。而 剛纔咱們直接在全局調中調用這個方法時,因爲這個方法運行時不在任何對象中,因此不存在任何宿主對象,因此若是在方法裏面寫$this的話會報致命錯誤。 那怎麼樣才能擁有宿主對象,而後直接調用。仔細看我剛纔講的同窗可能注意到,我剛纔說過"由於這個方法是被這個對象調用執行的,因此這個對象就是他的宿主 對象"。因此理論上說,咱們只要改變執行這個方法的所在環境,就能夠改變他的宿主對象。下面咱們來實驗下
class a{         public function say_name(){                 echo 'my name is'.$this->name;         } } class b{         public $name='xbs530';         public function run(){                 a::say_name();         } } $o=new b; $o->run(); 你們猜會輸出什麼。。。。。。。 你們能夠動手作一下試驗。。。。。 因爲a::say_name()是被對象$o調用的,因此方法裏面的$this天然指向了對象$o。很神奇吧。。。。 這個我以前發的那個PHP範圍解析操做符中都有講,好了基礎就講到這裏,下面直接上多繼承的代碼了,歡迎吐槽。。。。。 /*         多繼承基類                 注:要想實現類多繼承,必需首先繼承此基類 */          class multi_extends{                  public function __construct(){                 $this->_init_extends();         }                  protected function _init_extends(){                 if(property_exists($this,'_extends'))                 {                         $extends=&$this->_extends;                         foreach($extends as $class)                         {                                 $this->_extends($class);                         }                 }         }                  public function _extends($class_name){                 //分析目標                 $ref = new ReflectionClass($class_name);                                  //繼承公共屬性                 $property_list=$ref->getProperties(ReflectionProperty::IS_PUBLIC);                 foreach($property_list as $property)                 {                         $property_name=$property->name;                         $property_value=$property->getValue(new $class_name);                         if($property_name==='_extends')                         {                                 foreach($property_value as $c)                                 {                                         $this->_extends[]=$c;                                 }                         }else{                                 if(!property_exists($this,$property_name))                                 {                                         $this->{$property->name}=$property_value;                                 }                         }                 }                                  //繼承公共方法                 $method_list=$ref->getMethods(ReflectionMethod::IS_PUBLIC);                 foreach($method_list as $method)                 {                         $this->_extends_method[$method->name]=$method->class;                 }         }                  function __call($m,$a){                 if($c=$this->_extends_method[$m])                 {                         eval("$c::$m(".'$a'.");");                 }         } } header('content-type:text/html;charset=utf-8'); class a{         public $a=5;                  public function say_name(){                 echo '我叫'.$this->name.'<br>';         } } class b{         function say_age(){                 echo '我今年'.$this->age.'歲<br>';         }          } class c extends multi_extends{         public $_extends=array('a','b');                           public function say_hellow(){                 echo 'hellow '.$this->name.'<br>';         } } class d{         function say_goodbye(){                 echo 'goodbye '.$this->name.'<br>';         }          } class persion extends multi_extends{         public $_extends=array('c','d');                           public $name="熊寶山";         public $age="20";                            } //執行繼承後的方法 $o=new persion(); $o->say_name(); $o->say_age(); $o->say_hellow(); $o->say_goodbye();
相關文章
相關標籤/搜索