ホームページ >php教程 >php手册 >PHP はリフレクションを使用して多重継承 (非インターフェイス シミュレーション) を実際に実装します。

PHP はリフレクションを使用して多重継承 (非インターフェイス シミュレーション) を実際に実装します。

WBOY
WBOYオリジナル
2016-06-21 08:49:341228ブラウズ
昨日、PHP プログラムを作成していたときに、PHP の :: 演算子が非常に強力であることを発見しました。実際、その関数は親、sel、静的メンバーのプロパティ、および定数にアクセスするために使用されるだけではありません。



このシンボルは実際には PHP ではレンジ パーサーと呼ばれており、PHP php.net/manual/zh/ language.oop5.paamayim-nekudotayim.php の公式説明に記載されています。ただし、公式の中国語部分では簡単に紹介されているだけです

親、sel、静的メンバーのプロパティにアクセスし、定数の役割については英語が苦手なので読めないかもしれませんが、実装に関しては以下のような強力な機能があります。どれか見てください。
範囲演算子とは何ですか? 過去 2 年間のプログラミングの理解に基づくと、これらの単語はクラス内のメンバー属性とメンバー メソッドの範囲を定義する必要があると思います。名前空間のようなものです。
そして、 self::method(); は、実際には現在のスコープ内のメソッドメソッドの呼び出しを参照し、親クラスのメソッドをサブクラス内でオーバーライドする場合は、当然、親クラスのスコープを参照します。引き続き使用できます。parent::method() アクセスの理由です。また、self は常に宣言場所があるクラス自体を指し、parent は常に宣言場所があるクラスの親クラスを指し、継承コンテキストの影響を受けないことにも注意してください。
上で述べたように、:: は PHP では範囲解決演算子と呼ばれます。上で述べたように、parent と self の両方がクラス スコープの代名詞を指すことができるため、想像してみてください。特定の範囲を指すためにクラス名を使用しますか? 答えはもちろん「はい」です。これならできます

コードをコピー

  1. クラス a{
  2. パブリック関数デモ(){
  3. エコー 'abc';
  4. }
  5. }
  6. a::demo();

内部のデモ メソッドが静的メソッドではないことに気づいたかどうかはわかりませんが、a:: がクラス スコープを指しているため、その中のデモ メソッドにアクセスできます。公式にはそのようなサンプルコードがあり、上に投稿したリンクを詳しく見ることができます。


これが多重相続と何の関係があるのか​​と誰もが疑問に思うでしょう。心配しないでください。急いで熱々の豆腐を食べることはできません。 ! ! ! !
実際、この範囲演算子には優れた機能もあります。つまり、非静的パブリック メソッドがクラスの外部で呼び出された場合、メソッド内の $this ポインターは、現在実行されているオブジェクト自体 (ホスト オブジェクト) を指します。 . クラスがインスタンス化されるとき このとき、メソッド内の $this は常にインスタンス化されたオブジェクト自体を指しているため、このメソッドはこのオブジェクトによって呼び出され、実行されるため、このオブジェクトはそのホスト オブジェクトになります。このメソッドをグローバル呼び出しで直接呼び出した場合、このメソッドは実行時にどのオブジェクトにも存在しないため、ホスト オブジェクトが存在しないため、メソッド内に $this を記述すると致命的なエラーが報告されます。ホスト オブジェクトを所有し、それを直接呼び出すにはどうすればよいですか。私が今話した生徒たちを注意深く見てみると、「このメソッドはこのオブジェクトによって呼び出され実行されるため、このオブジェクトはそのホスト オブジェクトである」と私が言ったことに気づいたかもしれません。したがって、理論的には、このメソッドが実行される環境を変更する限り、そのホスト オブジェクトを変更できます。以下で実験してみましょう


クラス a{
パブリック関数say_name(){
echo '私の名前は'.$this->name;
}
}


クラス b{
public $name='xbs530';
パブリック関数 run(){
a::say_name();
}
}

$o=新しいb;
$o->run();
出力がどのようなものになるかは誰にもわかりません。 。 。 。 。 。 。
自分で試してみることもできます。 。 。 。 。

a::say_name() はオブジェクト $o によって呼び出されるため、メソッド内の $this は当然オブジェクト $o を指します。すごいですね。 。 。 。

これについては、以前に投稿した PHP 範囲解析演算子で説明しましたが、基本は完了したので、ここで説明します。多重継承のコードについては、すぐに説明します。 。 。 。 。

/*
複数の継承基本クラス
注: さらに多くの継承を実現するには、まずこの基本クラス
を継承する必要があります。 */
                                                 クラス multi_extends{
                                                パブリック関数 __construct(){
$this->_init_extends();
}
                                                 保護された関数 _init_extends(){
If(property_exists($this,'_extends'))
                                                            $extends=&$this->_extends;
foreach($extends as $class)
                                                                                                                                                   } }
}
                                                 パブリック関数 _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(新しい $class_name);
                        if($property_name==='_extends')
                        {
                                foreach($property_value as $c)
                                {
                                        $this->_extends[]=$c;
                                }
                        }その他{
                                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;
                }
        }
        
        関数 __call($m,$a){
                if($c=$this->_extends_method[$m])
                {
                        eval("$c::$m(".'$a'.");");
                }
        }
}













header('content-type:text/html;charset=utf-8');

クラス a{
        パブリック $a=5;
        
        パブリック関数say_name(){
                echo '我叫'.$this->name.'
';
        }
}

クラス b{
        関数say_age(){
                echo '我今年'.$this->age.'岁
';
        }
        
}


クラス c extends multi_extends{
        public $_extends=array('a','b');
        
        
        パブリック関数say_hello(){
                echo 'hello '.$this->name.'
';
        }
}


クラス d{
        関数say_goodbye(){
                echo 'さようなら '.$this->name.'
';
        }
        
}




クラス persion extends multi_extends{
        public $_extends=array('c','d');
        
        
        public $name="熊宝山";
        public $age="20";
        
        
        
}


//実行承認後のメソッド
$o=新しい人();
$o->say_name();
$o->say_age();
$o->say_hello();
$o->say_goodbye();
不明な白い場所がある場合は、QQ:987188548 相互検索を追加できます。また、ファイルも追加できます:xbs530@yeah.net 呵呵



声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。