42

この質問のように、StackOverflowに同様の質問がいくつかあることを私は知っています。

メソッドパラメータのオーバーライドがPHPの厳格な標準に違反しているのはなぜですか?例えば:

class Foo
{
    public function bar(Array $bar){}
}

class Baz extends Foo
{
    public function bar($bar) {}
}

厳格な基準:Baz :: bar()の宣言はFoo :: bar()の宣言と互換性がある必要があります

他のOOPプログラミング言語では可能です。なぜPHPで悪いのですか?

4

4 に答える 4

55

OOPでは、SOLID単一責任、オープンクローズ、リスコフ置換、インターフェース分離、依存性逆転の略です。

リスコフの置換原則は、コンピュータプログラムで、BarがFooのサブタイプである場合、そのプログラムの望ましいプロパティ(正確性、実行されるタスクなど)を変更せずに、 FooタイプのオブジェクトをBarタイプのオブジェクトに置き換えることができると述べています。 )。

強い型のプログラミング言語では、Fooメソッドをオーバーライドするときに、Barで署名を変更すると、元のメソッドと新しいメソッドが異なる署名で使用できるため、実際にはオーバーロードしています。PHPは弱い型であるため、コンパイラーは実際に呼び出しているメソッドを認識できないため、これを実現することはできません。(したがって、署名が異なっていても、同じ名前の2つのメソッドを持つことができない理由)。

したがって、Liskov Substituitionの原則の違反を回避するために、厳密な標準警告が発行され、子クラスのメソッドシグネチャの変更によって何かが破損する可能性があることをプログラマーに通知します。

于 2012-11-16T20:03:44.363 に答える
17

私はパーティーに遅れていることを知っていますが、答えは実際の問題を実際に説明していません。

問題は、PHPが関数/メソッドのオーバーロードをサポートしていないことです。型指定されていない言語で関数のオーバーロードをサポートすることは困難です。

ヒントが役立ちます。しかし、PHPでは非常に制限されています。理由はわかりません。たとえば、変数がintまたはブール値であることを示唆することはできませんが、配列は問題ありません。フィギュアに行こう!

他のオブジェクト指向言語は、関数のオーバーロードを使用してこれを実装します。つまり、関数のシグネチャは明らかに異なります。

したがって、たとえば、次のことが可能であれば、問題は発生しません。

class Foo
{
    public function bar(Array $bar){
        echo "Foo::bar";
    }
}

class Baz extends Foo
{
    public function bar(int $bar) {
        echo "Baz::bar";
    }
}


$foo = new Baz();
$bar = new Baz();
$ar = array();
$i = 100;

$foo->bar($ar);
$bar->bar((int)$i);

would output

Foo::bar
Baz::bar

もちろん、コンストラクターに関しては、php開発者は、それが好きかどうかにかかわらず、実装する必要があることに気づきました。したがって、最初のケースでは、単にエラーを抑制するか、エラーを発生させません。

これはばかげています。

知人はかつて、PHPは名前空間を実装する方法としてのみオブジェクトを実装したと言っていました。今、私はそれほど批判的ではありませんが、下された決定のいくつかはその理論を支持する傾向があります。

コードを開発するときは常に最大の警告をオンにします。それが何を意味し、何を意味するのかを理解せずに警告を通過させることは決してありません。個人的に私はこの警告を気にしません。私は自分が何をしたいのかを知っていますが、PHPはそれを正しく行いません。私はそれを選択的に抑制する方法を探してここに来ました。私はまだ道を見つけていません。

だから私はこの警告を罠にかけ、自分でそれを抑制します。恥ずかしい私はこれをする必要があります。しかし、私はSTRICTについて厳格です。

于 2013-10-15T06:42:53.250 に答える
4

パラメータを上書きできますが、署名は一致する必要があります。Arrayの前に出せば$bar問題ありません。

たとえば、パラメータを追加した場合、最初のパラメータに同じタイプのヒントがあれば問題ありません。これはどの言語でも良い習慣です。

于 2012-11-16T19:57:33.800 に答える
2

で宣言しFooたのはタイプである$bar必要がありますがarray、拡張Barでは、$barのタイプは宣言されません。

これはエラーではなく、警告です。メソッド定義を元の基本クラスと互換性があるようにする必要があります。ただし、自分が何をしているのかを知っている場合は(そして自分が何をしているのかを知っている場合にのみ)、安全に無視できます。

于 2012-11-16T19:58:07.567 に答える