我知道 StackOverflow 中有几个类似的问题,比如这个问题。
为什么覆盖方法参数违反了 PHP 中的严格标准?例如:
class Foo
{
public function bar(Array $bar){}
}
class Baz extends Foo
{
public function bar($bar) {}
}
严格标准: Baz::bar() 的声明应与 Foo::bar() 的声明兼容
在其他 OOP 编程语言中你可以。为什么 PHP 不好?
在 OOP 中,SOLID代表单一责任、开放封闭、里氏替换、接口隔离和依赖倒置。
Liskov 替换原则指出,在计算机程序中,如果Bar是Foo的子类型,则Foo类型的对象可以用Bar类型的对象替换,而不会改变该程序的任何所需属性(正确性、执行的任务等)。 )。
在强类型编程语言中,当重写 Foo 方法时,如果您更改 Bar 中的签名,您实际上是在重载,因为原始方法和新方法具有不同的签名。由于 PHP 是弱类型的,这是不可能实现的,因为编译器无法知道您实际调用了哪些方法。(因此你不能有两个同名的方法,即使它们的签名不同)。
因此,为避免违反 Liskov Substituition 原则,发出严格标准的警告,告诉程序员由于子类中方法签名的更改,可能会出现某些问题。
我知道我迟到了,但答案并没有真正说明实际问题。
问题是 PHP 不支持函数/方法重载。在无类型语言中支持函数重载是很困难的。
暗示有帮助。但在 PHP 中它非常有限。不知道为什么。例如,您不能暗示变量是 int 或 Boolean,但数组很好。去搞清楚!
其他面向对象的语言使用函数重载来实现这一点。也就是说函数的签名明显不同。
因此,例如,如果以下情况是可能的,我们就不会有问题
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 很严格。
您可以覆盖参数,但签名应该匹配。如果你Array在前面放出来$bar,就没有问题了。
例如,如果您添加了一个附加参数,那么只要第一个参数具有相同的类型提示,就没有问题。这是任何语言的好习惯。
因为您声明的Foo应该$bar是 type array,而在 extended 中Bar,$bar没有声明 's 的类型。
这不是错误,而是警告。您应该使方法定义与原始基类兼容。但是,如果您知道自己在做什么,则可以安全地忽略它(并且只有在您知道自己在做什么的情况下!!!)