14

PHP の奇妙な継承の問題と思われるものを見つけました。

PHPマニュアルから

保護されていると宣言されたメンバーは、クラス自体内で、継承されたクラスおよび親クラスによってのみアクセスできます。

私にとってこれは、A が B の保護されたメンバーにアクセスできることを意味しA instanceof BますB instanceof A

ただし、A と B の両方が Foo を拡張し、Foo に B で上書きされない保護されたコンストラクターがある場合、A 内から B のインスタンスを作成できます。A は のインスタンスではないため、これは意味がありません。 B であり、B は A のインスタンスではありません。A$b->test()内から保護されたメソッドを呼び出して、B で実装されたメソッドを実行することもできます (B が再宣言されない場合test()、Foo での実装が実行されます)。 B が保護されたコンストラクターを直接実装する場合、A 内から B のインスタンスを作成できないため、奇妙です。保護されたコンストラクター (親クラスでも宣言されている) にアクセスできないのは奇妙に思えますが、保護されたメソッド (親クラスでも宣言されています) にアクセスすることは問題ありません。

Foo を拡張しないクラス C を使用すると、期待どおりの動作が得られることに注意してください。C 内から B をインスタンス化しようとすると、保護されたコンストラクターにアクセスしようとしているため、致命的なエラーが発生します。パブリック コンストラクターを B に追加すると、それをインスタンス化することができますが (これは予想されます)、保護されたメソッドにアクセスすることはできませんtest()(これも予想される動作です)。C の代わりに A を使用すると、同じ動作が期待されます。

もう一度説明するサンプルコード:

class Foo {
    protected function __construct() {
        echo('Constructing ' . get_called_class());
    }

    protected function test() {
        echo('Hello world ' . __METHOD__);
    }
}

class A extends Foo {
    public function __construct() {
        parent::__construct();
    }

    public function testB() {
        // Both of these lines work
        $b = new B();
        $b->test();
    }
}

class B extends Foo {
    protected function test() {
        echo('Hello world Again ' . __METHOD__);
    }
}

class C {
    public function __construct() {
    }

    public function testB() {
        // Both of these lines cause fatal errors
        $b = new B();
        $b->test();
    }
}

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

$c = new C();
$c->testB();

私はおそらく何かを見ていませんが、何を見つけることができません。誰かが私に行動を説明できますか?

4

2 に答える 2

6

で保護されていると宣言されているため、これらのメソッドにアクセスできますFoo。これは、親であり、アクセスの許可を与えます。親から宣言を削除し、で保護されたメソッドを宣言するBと、致命的なエラーが発生します。

これは、PHPのバグとして報告されていますhttps://bugs.php.net/bug.php?id=50892

于 2012-10-05T12:54:44.277 に答える
1

これには根拠がなく、2 年前に報告されています: https://bugs.php.net/bug.php?id=52120

于 2012-10-05T12:58:19.120 に答える