python - 重载(而不是压倒一切)是否违反了 Liskov 替换原则?
问题描述
有大量关于 LSP 的讨论,但所有讨论似乎都过于模糊。
AFAIK,LSP 指出要正确覆盖(而不是重载)子类中的超类方法,应确保子方法:
- 不会产生父方法在任何情况下都不会引发的新异常类型
- 与父方法具有相同的签名(在强类型语言的情况下)
- 与签名具有相同的语义含义
- 返回相同类型的值
- 返回具有相同语义的值
我的意思是,semantic meaning
如果基类方法暗示它返回int
并且这int
意味着美元或欧元,那么重载的方法也应该暗示返回的值是美元或欧元,并且即使在一种情况下返回“RUB”也会违反语言服务提供商。
但是如果我的基类看起来像这样(示例在 Python 中):
class A:
func(x: int) -> int
return x*2
class B(A):
func(x: int, y: string) -> int
return x*y
所以我的问题中有两个子问题:
contract
这个词在更实际的意义上是什么意思?是同义词interface
吗?- 使用基类中不存在的签名(作为参数列表的一部分)重载是否违反 LSP?
解决方案
答案取决于语言。
在 Java、C++、C# 等典型的 stronly 类型的 OO 语言中,当您编写类似的方法调用时a.func(b,c)
,实际调用的方法取决于方法名称以及接收类型(a
本例中为),以及参数的数量和类型。
在这样的语言中,具有不同数量的参数或不同类型的参数的方法是完全不同的方法。拥有不同数量的参数就像拥有不同的名称一样。当您“重载”一个方法时,就像创建一个具有不同名称的方法一样,因此您不会通过重载基类中的方法来违反 LSP。
不过,您的问题似乎与 python 有关,并且在典型的动态类型语言(如 python、JavaScript 等)中,当您编写类似a.func(b,c)
的方法调用时,仅按名称查找要调用的方法(在与接收对象)。在这样的语言中,没有方法或函数的重载。
在您的示例中,您已经使用双参数函数覆盖了单参数定义。func
这意味着派生类的消费者不能再func
使用一个参数调用,这确实违反了 LSP。
推荐阅读
- laravel - 如何仅修复路由问题/路由在实时服务器上工作而不是其他?
- pandas - 大熊猫分组并总和显示值
- javascript - 如何在本机反应中转到顶部选项卡导航中的另一个屏幕
- azure-active-directory - MSAL SDK 与 ROPC 身份验证流程结合证书断言 - 是可能的
- python - 使用 Python 将数据推送到在线 GitHub 存储库
- drupal - Drupal 7如何仅发送drupal_email密件抄送而不发送地址
- qt - 捕捉 QML 组件状态/进度变化信号
- java - Spring Integration IMAP:由于 Outlook 365 中的病毒扫描,无法从邮件中读取附件
- c# - 声明数据库上下文的控制器级实例
- c++ - 为什么使用“return”-fpermissive 出现 void 错误问题