php利用反射真正實現多繼承(非介面類比)

來源:互聯網
上載者:User
昨天我在寫PHP程式的時候,無意發現在PHP的::操作符非常強大,不僅僅是只用在訪問parent,sel,靜態成員屬性、常量上面,其實他的功能強大了去了



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

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

複製代碼
  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();
有不明白的地方可以加QQ:987188548互相探討下,郵件也可以:xbs530@yeah.net  呵呵


相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.