2012-03-15 6 views
14

いくつかのPHPコードを見直しながら、私は奇妙なことを発見しました。ここでの簡単な例を示す図である:PHP継承、子変数を使用する親関数

ファイルA.php:

<?php 
class A{ 
    public function methodA(){ 
     echo $this->B; 
    } 
} 
?> 

ファイルB.php:

<?php 
    class B extends A{ 
     public $B = "It's working!"; 
    } 
?> 

ファイルtest.phpを:

<?php 
    require_once("A.php"); 
    require_once("B.php"); 
    $b = new B(); 
    $b->methodA(); 
?> 

ランニングtest.phpは「働いています!」と表示しますが、質問はなぜ機能していますか? :)これは機能ですか、バグですか?クラスAのメソッドmethodAは、クラスBに属し、OOPで動作しないメソッドを呼び出すこともできます。

+1

一つの方法は、Bを定義せずに、クラス「C」を作成すること、そして何が起こるかを見るであろう。あなたがしたことは、実験のために行われなかった場合、あなたは狂ったデザインと見なされますが、PHPはその状況で動作させるのに十分なほどスマートになるかもしれません。 –

+1

OOPは、サブクラスメソッドの呼び出しが基本クラスから機能するかどうかは何も言いません。スーパークラスのメソッドは、(オーバーライドされていない限り)サブクラスに利用可能でなければならないと言われていますが、他の方法については静かです。実際、現存する最も純粋なOOP言語のいくつかは気にしません。 – cHao

+0

5+ upvotes?どうして? –

答えて

12

クラスBのインスタンス化のみです。すぐにAを無視し、methodA()がクラスBの一部であるとふりまとめてください。

クラスBAになると、Aの機能がすべて取得されます。 $this->Bは、コードが実行されるまで評価されません。したがって、B$this->Bが存在するため、エラーは発生せず、発生しません。クラスAは、したがって、それがクラスAから方法methodA()を継承から

+3

パブリックメンバー変数でのみそのように動作します。 – hakre

6

PHPは動的言語です。メソッドとデータメンバーは実行時に評価されます。メソッドを呼び出したりメンバにアクセスしたりすると、PHPは実際にこのメソッドやメンバがこのオブジェクトでアクセスできるかどうか、または継承階層のどこにでも存在できるかどうかを調べるために、ソートのハッシュテーブルを検索します。

継承だけでなく、実行時にいつでもオブジェクトに任意のデータを割り当てることができ、クラス内のコードは$ this-> somethingを使用してアクセスすることができます。 。

0

クラスBは延び

2

PHPは、動的言語であるため、使用しているインスタンス上に存在することができるプロパティまたはメソッドを呼び出すと間違って何もありませんそれ(この場合、サブクラスBのインスタンス)

1

PHPは動的言語です。 methodA()がBのインスタンスに対して呼び出されると、Bのメンバー$ Bは実際に存在します。

$a = new A(); 
$a->methodA(); 

は機能しません。

一部の動的言語では、実行時にメソッドを定義することさえできます。

1

それは私にとって理にかなっています。 $ this-> Bは実行時に評価され、その前に(クラスBがインスタンス化されると)値が設定されるため、結果として得られるオブジェクトでは$ Bが使用可能になります。正しく設定してください。

実行するまでその存在がチェックされていないので、メソッドでもこれを行うことができます(ただし、親クラスでabstractを宣言して強制的に実装するメソッドの場合は通常です) 。

1

これは、OOPが動作する方法です。ちょっと奇妙に思えるかもしれません。なぜなら、Aが最初に何であるのかを知る必要があるからです(実際にはいくつかの言語ではコンパイラの警告が出ます)が、使用するサブクラスあなたの関数が探している変数を定義しています。 A()のインスタンスからmethodA()を呼び出した場合、「未定義」エラーが発生します。 - それはまだそれが現在のものですので、特別なものはなく、

class A { 
    public $b = "Derp"; 
} 
class B extends A { 
    function sayIt() { echo $this->b; } 
} 
$a = new A(); 
$a->sayIt(); 
3

$thisだけでオブジェクト変数です:奇妙なことだろうか今

は、(読み:間違っ)をTHISが働いていた場合でありますオブジェクト変数です。

$B::Bはパブリックメンバー変数であるため、Bのインスタンスへの参照が到達可能などこからでもアクセスできます。オブジェクト変数を使用します。

パブリックメンバーはどこでもアクセスでき、どんな機能でも、A::methodA()からアクセスすることができます。

実際に不思議そうなことはあまりありません。あなたの例におけるクラス継承は、A::methodA()が呼び出されたときに、$this "パラメータ"の形のオブジェクト変数の(見えない)渡しにのみ関係します。

おそらくそれがより見えるように、次の例を参照してください:テストする

function methodA($object) { 
    echo $object->B; 
} 

class B { 
    public $B = "It's working!"; 
    public function methodA() { 
     methodA($this); 
    } 
} 
+0

$この変数はクラスBのインスタンスです。同様の例の変数では、これもBのインスタンスです。javaの例では、クラスAとBの両方で変数Bを定義する必要がありました。クラスAのものを出力します。 –

+0

PHPでは、メンバを保護したい場合は、Aで保護されたものとして定義する必要があります.BがAから拡張されているので、AとBの両方の定義それにアクセスすることができます。保護されたメンバーは外部からは見えません。プライベートメンバーは現在の定義でのみプライベートなメンバーなので、PHPのプライベートメンバーの場合、AはBで定義されているとアクセスできません。 – hakre

関連する問題