为什么覆盖方法参数违反了 PHP 中的严格标准?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13423494/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 05:23:06  来源:igfitidea点击:

Why is overriding method parameters a violation of strict standards in PHP?

phpoop

提问by Kaern Stone

I know there are a couple of similar questions here in StackOverflow like this question.

我知道 StackOverflow 中有几个类似的问题,比如这个问题

Why is overriding method parameters a violation of strict standards in PHP? For instance:

为什么覆盖方法参数违反了 PHP 中的严格标准?例如:

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

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

Strict standards: Declaration of Baz::bar() should be compatible with that of Foo::bar()

严格的标准: Baz::bar() 的声明应该与 Foo::bar() 的声明兼容

In other OOP programming languages you can. Why is it bad in PHP?

在其他 OOP 编程语言中,您可以。为什么它在 PHP 中很糟糕?

回答by Tivie

In OOP, SOLIDstands for Single responsibility, Open-closed, Liskov substitution, Interface segregation and Dependency inversion.

在 OOP 中,SOLID代表单一职责、开闭、Liskov 替换、接口隔离和依赖倒置

Liskov substitutionprinciple states that, in a computer program, if Baris a subtype of Foo, then objects of type Foomay be replaced with objects of type Barwithout altering any of the desirable properties of that program (correctness, task performed, etc.).

Liskov 替换原则指出,在计算机程序中,如果BarFoo的子类型,则可以将Foo类型的对象替换为Bar类型的对象,而不会改变该程序的任何理想属性(正确性、执行的任务等)。 )。

In strong-typed programming languages, when overriding a Foo method, if you change the signature in Bar, you are actually overloadingsince the original method and the new method are available with different signatures. Since PHP is weak typed, this is not possible to achieve, because the compiler can't know which of the methods you are actually calling. (hence the reason you can't have 2 methods with the same name, even if their signatures are different).

在强类型编程语言中,当覆盖 Foo 方法时,如果更改 Bar 中的签名,实际上是在重载,因为原始方法和新方法具有不同的签名。由于 PHP 是弱类型的,这是不可能实现的,因为编译器无法知道您实际调用的是哪个方法。(因此你不能有两个同名的方法,即使它们的签名不同)。

So, to avoid the violation of Liskov Substituition principle, a strict standard warning is issued, telling the programmer something might break due to the change of the method signature in the child class.

因此,为了避免违反 Liskov Substituition 原则,发出了严格的标准警告,告诉程序员由于子类中方法签名的更改可能会导致某些问题。

回答by DeveloperChris

I know I am late to the party but the answers don't really spell out the actual problem.

我知道我迟到了,但答案并没有真正说明实际问题。

The problem is PHP doesn't support function/method overloading. It would be difficult to support function overloading in an untyped language.

问题是 PHP 不支持函数/方法重载。在无类型语言中支持函数重载是很困难的。

Hinting helps. but in PHP it is very limited. Not sure why. For example you cannot hint a variable is an int or Boolean yet array is fine. Go figure!

暗示有帮助。但在 PHP 中它是非常有限的。不知道为什么。例如,您不能暗示变量是 int 或 Boolean 但数组很好。去搞清楚!

Other object orientated languages implement this using function overloading. Which is to say the signature of the function is obviously different.

其他面向对象的语言使用函数重载来实现这一点。也就是说函数的签名明显不同。

So for example if the following was possible we would not have an issue

因此,例如,如果以下是可能的,我们就不会有问题

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

Of course when it came to constructors the php developers realised they have to implement it, Like it or not! So they simply suppress the error or not raise it in the first case.

当然,当谈到构造函数时,php 开发人员意识到他们必须实现它,不管你喜不喜欢!因此,他们只是在第一种情况下抑制错误或不引发错误。

Which is silly.

这是愚蠢的。

An acquaintance once said PHP implemented objects only as a way of implementing namespaces. Now I am not quite that critical but some of the decisions taken do tend to support that theory.

一位熟人曾经说过,PHP 实现对象只是作为实现命名空间的一种方式。现在我不是很挑剔,但做出的一些决定确实倾向于支持该理论。

I always have maximum warnings turned on when developing code, I never let a warning go by without understanding what it means and what the implications are. Personally I don't care for this warning. I know what I want to do and PHP doesn't do it right. I came here looking for a way to selectively suppress it. I haven't found a way yet.

在开发代码时,我总是打开最大警告,我从不放过警告而不了解它的含义和含义。我个人不关心这个警告。我知道我想做什么,而 PHP 做得不对。我来这里是为了寻找一种有选择地抑制它的方法。我还没有找到方法。

So I will trap this warning and suppress it myself. Shame I need to do this. but I am strict about STRICT.

所以我会捕获这个警告并自己压制它。可惜我需要这样做。但我对 STRICT 很严格。

回答by Brad

You can override parameters, but the signature should match. If you had put Arrayout in front of $bar, there would be no problem.

您可以覆盖参数,但签名应该匹配。如果你Array在前面放了$bar,就不会有问题。

For example, if you had added an additional parameter, there would be no problem, provided the first parameter had the same type hinting. This is good practice in any language.

例如,如果您添加了一个附加参数,则没有问题,只要第一个参数具有相同的类型提示。这在任何语言中都是很好的做法。

回答by Madara's Ghost

Because you declared on Foothat $barshould be of type array, while in the extending Bar, $bar's type isn't declared.

因为你宣布Foo$bar应该是类型array,而在扩大Bar$bar“S型未声明。

This isn't an error, it's a warning. You should make the method definition compatible with the original, base class. You can, however, safely ignore it if you know what you're doing (and onlyif you know what you're doing!!!)

这不是错误,而是警告。您应该使方法定义与原始基类兼容。但是,如果您知道自己在做什么(并且当您知道自己在做什么!!!)