昨天我在寫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
你們確定又疑惑這跟多繼承有什麼關係呢,別急,心急吃不了熱豆腐的!!!!!
其實這個範圍操做符還有一個很大的特性,就是當在類外部調用一個非靜態公共方法時,方法內部的$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();