2012-02-13 10 views
1

私はクラスが最初にあります。$nameは 'bob'に設定されています。子クラスでは、$nameを「カレン」に設定しましたが、動作しません。子クラスの親変数を定数値でオーバーライドできないのはなぜですか? (PHP)

私のエコーステートメントでは、第1のものは「カレン」の代わりに「ボブ」と言います。 2番目は、子クラスのメソッドを使用して、しかし、動作します。

この現象はなぜですか?

class First { 

    public $name; 

    public function __construct() { 

     $this->name = 'bob'; 
    } 
} 

class Third extends First { 

    public $name = 'Karen'; 
    public function set_name ($name) { 
     $this->name = $name; 
    } 
} 

$instance_of_third = new Third; 
$third_name = $instance_of_third->name; 

echo "<br />We're looking for Karen: $third_name<br />"; 
// $third_name here is 'bob' from parent class 

$instance_of_third->set_name("Karen"); 
$third_name = $instance_of_third->name; 
// $third_name here is 'Karen' only after using set_name() 
echo "<br />We're looking for Karen: $third_name<br />"; 

EDIT:出力が正確であったことを示す2行を追加しました。

子クラスで$nameが明示的に 'Karen'に設定されていても、set_name()関数を使用して変更しない限り、 'bob'と表示されます。

答えて

4

Thirdには独自のコンストラクタがないため、コンストラクタをFirstから継承します。継承は、スーパータイプとサブタイプの間の動作としての関係を作成します。

したがって、Thirdの新しいインスタンスを作成すると、インスタンスには$nameというプロパティが 'Karen'になりますが、継承されたコンストラクタが呼び出されます。そしてその名前をBobに設定します。サブタイプでその動作をしたくない場合は、空のコンストラクタをThirdに追加する必要があります。

class Third extends First 
{ 
    public function __construct() 
    { 
     // prevents parent First::__construct 
    } 
} 

demo

代替はCTORを除去(あるいは少なくともそれに$nameを設定されていない)とボブの親で$name性をプリセットすることであろう。その後、最初のアイデアが有効になります。

class First 
{ 
    public $name = 'Bob'; 
} 

class Third extends First 
{ 
    public $name = 'Karen'; 
} 

demo

PHPマニュアルでの継承と可視性の章を確認してください:

+0

奇妙なことに、クラスを拡張してプロパティの1つを変更したい場合、コンストラクタコードを書く代わりに、明示的に行うことができると思います。 –

+1

@ButtleButkus私の更新を見てください。出来るよ。 'new Foo' - >デフォルトのプロパティを持つ' Foo'の新しいインスタンスを作成し、そのインスタンスに対して '__construct'を自動的に呼び出して追加の初期化を行います。 – Gordon

1

classのオブジェクトを作成すると、コンストラクタが呼び出されます。

親クラスのコンストラクタは、あなたのケースで$ nameの値を上書きしています。

+0

子クラスに$ nameが設定されています。あなたの答えは、コンストラクタが最初に呼び出されたと言うようですが、それは何が起こっているのではありません。 $ nameが最初に設定された後、コンストラクタによって上書きされるようです...? –

+0

いいえ、変数が最初に初期化され、次にコンストラクタが呼び出されます – Gaurav

+0

うーん、それは変です。ありがとうございました。 –

1

フィールドが初期化された後にコンストラクタが呼び出されるので、$ nameフィールドがオーバーライドされるためです。

+0

それは起こっているようですが、これは奇妙ではありませんか?子クラスで明示的に値を設定した場合、その値が取得されると想定していませんか?またはそれを変更するために子クラスのコンストラクタを使用しますか? –

+0

コンストラクタのようなメソッドで値を変更しないと、その値が得られます。単純にあなたのコードは言う:1)名前= 'カレン'でオブジェクトを作成する。 2) 'new'はコンストラクタを呼び出し、それを 'Bob'に変更します。 3)オブジェクトは変数に代入されます。 – meze

0

インタープリタは、私たちと同じように、上から下に読み込む可能性が最も高いです。

最初の例では、public変数をKarenに設定しますが、子クラスは最初のクラスのコンストラクタを継承するため、 "Bob"が設定されます。

+0

ええと、上から下への読み込みでは、継承された値 'bob'で子クラスをインスタンス化し、子クラスで 'Karen'に設定して 'bob'を上書きすると思います。 –

+0

はい、クラスがインスタンス化されると、コンストラクターが呼び出され、Bobに設定されます。 :) – Jeff

1

コンストラクタはデフォルト値をオーバーライドします。またThirdクラスに拡張します

$first_instance = new First("Bob"); 

:その後でそれを呼び出す

class First { 
    public $name; 
    public function __construct($name) { 
     $this->name = $name; 
    } 
} 

:(それはデフォルト値のインスタンス化の後に呼ばれています一般的にので)、より堅牢な方法は、そうようなものになるだろう。

0

はstaticとして$名を宣言してください。 Third :: $ nameなどを使ってアクセスします。

class First { 

    public static $name; 

    public function __construct() { 

     self::$name = 'bob'; 
    } 

    // edit late static binding 
    public function getName() { 
     return static::$name; 
    } 


} 

class Third extends First { 

    public static $name = 'karen'; 

} 

$instance_of_third = new Third(); 
//$third_name = $instance_of_third::$name; 
$third_name = $instance_of_third->getName();  

echo "<br />We're looking for Karen: $third_name<br />"; 
+0

はOPの問題を解決しません。むしろ、それはありますが、もはやコアの問題を解決するものではありません。 OPはPHPで継承がどのように機能するかを理解するのに問題があります。 – Gordon

+0

したがって、静的変数は簡単な代入によってオーバーライドできます。あなたのコードは動作しますが、Dreamweaverが「$ third_name = $ instance_of_third :: $ name;」でエラーを強調表示するのは奇妙です。 –

+0

私は例を編集しました。親クラスでgetName()という関数を宣言することもできます。 getNameは、クラスに関連付けられた名前を返します。これはPHP 5.3で動作し、late static bindingと呼ばれています。例として、$ first = new First(); $ first-> getName()はBobなどを返します。 – busypeoples

関連する問題