[英]If Field > CharField > EmailField, does EmailField break Liskov Substitution Principle with CharField?
[英]Does overloading (not overriding) break the Liskov subsitution principle?
有大量关于 LSP 的讨论,但所有讨论似乎都过于模糊。
AFAIK,LSP 指出要正确覆盖(而不是重载)子类中的超类方法,应确保子方法:
通过semantic meaning
,我的意思是,如果基本 class 方法暗示它返回int
并且这个int
意味着,比如说,美元或欧元,那么重载的方法还应该暗示返回值是美元或欧元,并且即使在一种情况会违反 LSP。
但是如果我的基础 class 看起来像这样(示例在 Python 中):
class A:
func(x: int) -> int
return x*2
class B(A):
func(x: int, y: string) -> int
return x*y
所以我的问题中有两个子问题:
contract
这个术语在更实际的意义上是什么意思? 是interface
的同义词吗?答案取决于语言。
在典型的强类型 OO 语言中,如 Java、C++、C# 等,当您编写方法调用时,方法调用(如a.func(b,c)
接收类型(本例中为a
的类型),以及arguments的数量和类型。
在这样的语言中,具有不同数量的 arguments 或不同类型的 arguments 的方法是完全不同的方法。 拥有不同数量的 arguments 就像拥有不同的名称一样。 当您“重载”一个方法时,就像创建一个具有不同名称的方法一样,因此您不会通过从基础 class 重载一个方法来违反 LSP。
不过,您的问题似乎是关于 python 的,并且在典型的动态类型语言(如 python、JavaScript 等)中,当您编写像a.func(b,c)
这样的方法调用时,只查找调用方法, (在与接收对象关联的表中查找)。 在这样的语言中,没有方法或函数的重载。
在您的示例中,您已经用两个参数 function覆盖了func
的单参数定义。 这意味着您派生的 class 的消费者不能再使用一个参数调用func
,这确实违反了 LSP。
在现实生活中,合同是甲方和乙方对彼此的期望,即他们提供的保证。 编程相同:
它是方法的接口和文档的组合。
当我们说一个孩子应该遵循相同的契约时,我们的意思是,如果我们用另一个 ChildC 替换实现,那么将遵循与父级中描述的相同的约束,相同的行为。
例如,在 Java 中,我们有 Map 的概念(类似于 Python 中的 Dict),并且有 2 个不同的实现:HashMap 和 LinkedMap。 一个不保留加法的顺序,另一个 - 保留。 但是在合同中(在界面及其文档中)没有人说应该保留订单。 因此,如果我们的代码使用 HashMap 然后我们用 LinkedHashMap 替换它 - 它仍然可以完成父文档和签名所需的一切。
还有另一个实现:ConcurrentHashMap。 现在,它违反了 LSP。 因为 HashMap,LinkedHashMap 可以有 null 键,而 ConcurrentHashMap 不能。 因此,我们不能只用另一种实现替换一个实现——如果客户端实际上将 null 放在那里,它可能会破坏事情。
Map 的文档缓解了该问题,该文档称某些实现可能不接受 null,但这更像是一种 hack。
至于重载-您正在创建一个具有相同名称的单独方法,它不必遵循第一个合同。 这些方法可能根本没有共同之处。 尽管如其他答案中所述 - Python 中没有方法重载,但您只是用新方法替换旧方法,因此在子类中完成时这是一种覆盖。
PS:如果您使用策略或命令 - 实施会完全不同。 所以 LSP 在这里不适用。 但是他们仍然需要遵循父级中描述的通用合同。
要理解 LSP 的含义,口号“不再要求,promise 也不少”有很大帮助。 覆盖方法不能要求更多的 arguments 或更多特定类型的 arguments(即,它们必须是逆变的)。 它必须 promise 返回与被覆盖方法相同或更具体的类型的值(即,它必须是协变的)。
语义约束是覆盖方法必须在子类中执行与在超类中执行的“相同的事情”。 这种做同样事情的概念不容易形式化,它取决于类本身的含义。 但是,如果覆盖方法调用了被覆盖的方法,这是语义一致性的强烈标志。
重载与 LSP 无关。 这只是允许不同方法具有相同名称的编译时技巧。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.