web-dev-qa-db-ja.com

クラス定数とプロパティのオーバーライド

以下のシナリオでは、クラス定数がインスタンス変数に対して継承される方法に違いがある理由をよりよく理解したいと思います。

<?php
class ParentClass {
    const TEST = "ONE";
    protected $test = "ONE";

    public function showTest(){
        echo self::TEST;
        echo $this->test;
    }
}

class ChildClass extends ParentClass {
    const TEST = "TWO";
    protected $test = "TWO";

    public function myTest(){
        echo self::TEST;
        echo $this->test;
    }
}

$child = new ChildClass();
$child->myTest();
$child->showTest();

出力:

TWO
TWO
ONE
TWO

上記のコードでは、ChildClassにはshowTest()メソッドがないため、ParentClass showTest()メソッドが継承によって使用されます。結果は、メソッドがParentClassで実行されているため、TEST定数のParentClassバージョンが評価されているのに対し、継承を介してChildClassコンテキスト内で評価されているため、ChildClassメンバー変数$ testが評価されています。

私はドキュメントを読みましたが、このニュアンスについての言及を見ることはできません。誰かが私のために光を当てることができますか?

88
Tom Auger

self::継承を意識せず、常に実行されているクラスを参照します。php5.3+を使用している場合は、static::TEST as static::は継承を認識します。

違いは、static::は「遅延静的バインディング」を使用します。詳細はこちらをご覧ください:

http://php.net/manual/en/language.oop5.late-static-bindings.php

これが私が書いた簡単なテストスクリプトです。

<?php

class One
{
    const TEST = "test1";

    function test() { echo static::TEST; }
}
class Two extends One
{
    const TEST = "test2";
}

$c = new Two();

$c->test();

output

test2
175
David Farrell

PHPでは、selfは、呼び出されたメソッドまたはプロパティが定義されているクラスを指します。したがって、あなたの場合、selfChildClassを呼び出しているため、そのクラスの変数を使用します。次に、selfParentClassを使用するため、そのクラスの変数を参照します。

子クラスで親クラスのconstをオーバーライドする場合は、親クラスの次のコードをこれに合わせて調整します。

public function showTest(){
    echo static::TEST;
    echo $this->test;
}

staticキーワードに注意してください。これは「遅延静的バインディング」を使用します。これで、親クラスは子クラスのconstを呼び出します。

14
w00