gpt4 book ai didi

php - 我对 Liskov 替换原则有什么误解

转载 作者:搜寻专家 更新时间:2023-10-31 21:08:17 24 4
gpt4 key购买 nike

我以为我了解 LSP,但看来我完全错了。我有以下类(class):

class PrimitiveValue {
}

class StringValue extends PrimitiveValue {
}

class A {
public function foo(StringValue $value) {
}
}

class B extends A {
public function foo(PrimitiveValue $value) {
}
}

注意基类A接受子类 StringValue作为参数类型,子类B接受父类PrimitiveValue。我之所以这样说,是因为到处都会有人问类似的问题,只是类型相反。

根据我的理解,B 类中的方法 foo() 接受父方法接受的任何内容,再加上更多,因为它接受基类型 PrimitiveValue。因此,任何只看到类 A 的调用者都会传递 B 可以处理的值,而不会违反 LSP。知道它是 B 的调用者可以做出更强的假设,并可以自由传递其他 PrimitiveValue 子类型。

然而,当我执行代码时,出现错误:

严格 (2048):B::foo() 的声明应与 A::foo(StringValue $value) 兼容 [APP/Controller/TestLocalController.php,第 17 行]

我哪里错了?我认为最有帮助的是一个示例,说明如何传递违反代码对该值所做假设的值。假设很清楚我要实现的目标,还请添加有关如何正确执行此操作的代码。

最佳答案

What am I getting wrong? I think most helpful would be an example of how a value can be passed that violates the assumptions the code makes about that value.

你没有误解LSP,在子类方法中允许更大的类型并不违反原则;事实上,你所描述的是contravariant method argument types。 ,由于设计或实现困难,PHP 不支持某些内容。

就个人而言,我对这种方法的唯一保留意见是子类中较弱类型的处理被父类(super class)隐藏了。

Assuming that it is clear what I'm trying to achieve, please also add code on how to do it correctly.

PHP 中的方法参数类型是不变的,即每个参数的类型(如果在父级中提供)在覆盖方法时必须完全匹配。虽然此行为已在 past 中讨论过再次长大recently随着return type hinting的介绍,即使在下一个主要版本中也不能保证可用。

为了克服这个问题,您目前被迫让原始类型和派生类型都实现相同的接口(interface),然后在父类和子类中使用该接口(interface),如 this answer 所述。 .

关于php - 我对 Liskov 替换原则有什么误解,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28362180/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com