7

TestUK と、TestUK を拡張する TestFR という 2 つの php クラスがあります。

どちらのクラスも、2 つの異なるドメインへのリクエストを生成するために使用されます。しかし、継承に問題があり、その理由がわかりません。

実際に使用する必要があるドメインを取得するために上書きされる「get_domain」という名前のメソッドが 1 つあります。を介して直接呼び出すとTestFR::get_domain()、期待される結果が得られます。しかし、TestFR によって上書きされていないが、 を使用するメソッドを呼び出すとself::get_domain()、間違ったドメインを受け取ります。

メソッド do_stuff を TestUK から TestFR にコピー アンド ペーストするだけで、期待どおりの結果が得られます。しかし、同一の (!) コードをコピーして貼り付けることは、私が避けようとしていたことです。

これの理由は何ですか?PHP でのクラス継承の経験はあまりありませんが、これは問題なく動作することを期待していました。または、私のアプローチは完全に欠陥がありますか?

<?php
class TestUK {

    const DOMAIN_UK = 'http://www.domain.co.uk';
    const DOMAIN_FR = 'http://www.domain.fr';

    static function get_domain(){
        return self::DOMAIN_UK;
    }

    static function do_stuff(){
        echo self::get_domain();
    }

}

class TestFR extends TestUK {

    static function get_domain(){
        return self::DOMAIN_FR;
    }

}

// Works as intended:
// Expected and actual output: http://www.domain.fr
echo TestFR::get_domain();

// Does NOT work as intendes:
// Expected Output: http://www.domain.fr
// Actual Output:   http://www.domain.co.uk
TestFR::do_stuff();
?>
4

2 に答える 2

17

これは、キーワードselfが、メソッドが呼び出されたクラスではなく、表示されるクラスを参照するためです。後者の機能については、次のキーワードで遅延静的バインディングを使用する必要があります。static

static function do_stuff(){
    echo static::get_domain();
}

とはいえ、このコードは本当に臭いです。static単なるインスタンスメソッドではなく、なぜすべてなのですか? 抽象基本クラスを拡張するのではなく、拡張するのTestFRはなぜですか?TestUKTest

すべてを非静的メソッドに変換する方がはるかに良いでしょう。おまけとして、問題はすぐに消えます。

于 2013-09-17T11:17:31.900 に答える
1

のように呼び出します (php >= 5.3 を使用している場合)

static::get_domain();
于 2013-09-17T11:18:11.003 に答える