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

2022-08-30 11:40:38

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

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

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

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

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

在其他OOP编程语言中,你可以。为什么它在PHP中不好?


答案 1

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

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

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

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


答案 2

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

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

提示会有所帮助。但在PHP中,它非常有限。不知道为什么。例如,您不能暗示变量是整数或布尔值,但数组很好。去图吧!

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

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

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做得不对。我来到这里寻找一种选择性地压制它的方法。我还没有找到办法。

因此,我将捕获此警告并自己压制它。可惜我需要这样做。但我对严格要求。


推荐