1

PHPクラスで関数ポリモーフィズムを使用したいと考えています。いくつかの子クラス関数の関数の入力型をチェックするつもりです。

class A
{
    public function setValue(Type $value)
    {
    }
}

class B extends A
{
    public function setValue(XType $value)
    {
    }
}

class C extends A
{
    public function setValue(ZType $value)
    {
    }
}
$b = new B();
$b->setValue(new XType());

class Type {};
class XType extends Type;
class ZType extends Type;

私が探している動作は、setValueが間違った引数の型で呼び出された場合に PHP が例外をスローすることです。

上記のコードを使用すると、エラーが発生します。

ランタイム通知: B::setValue() の宣言は、B.php 行の A::setValue(Type $value) と互換性がある必要があります..

これは、私が望む動作を得ることができた方法です:

class B extends A
{
    public function setValue(Type $value)
    {
        if (!$value instanceof XType) {
            throw new \Exception("value $value not allowed, should be of type XType");
        parent::setValue($value);
        }
    }
}

しかし、PHP コアにそのコードのビットを処理させてくれることをうれしく思います :)

私は十分に明確ではなかったことがわかります..

呼び出し元にデフォルトの動作A::setValue()と、特定の子クラスに関する特定の動作B::setValue()を提供しようとしています。したがって、呼び出し元がB::setValue()を呼び出そうとするとサポートされていない型の場合、エラーが発生しますが、たとえばD::setValue()を呼び出すと、デフォルトのA::setValue()が取得されます。

4

1 に答える 1

1

すでに機能しているものは、実行しているinstanceofチェックの必要はありません。引数の型ヒントで型を宣言するだけです。

あなたのコードの問題点は、それが適切なポリモーフィズムではないということです。これは、通知 (注:エラーではありません) が伝えたいことでもあります。サブクラスには、親クラスとは異なる型の引数が必要です。これらの型が関連している場合でも、親クラスの特定のインスタンスを子クラスの 1 つに置き換えることはできません。それがポリモーフィズムの破壊です。子クラスがより特化した型を必要とする場合、その宣言は親と互換性がなくなるため、完全にポリモーフィックではなくなります。

適切なポリモーフィズムでは、これは機能するはずです:

if (rand(0, 1)) {
    $obj = new A;
} else {
    $obj = new B;
}

$obj->setValue(new Type);

あなたがやろうとしていることでは、うまくいきません。

于 2012-12-13T13:34:54.527 に答える