3

有一本书说有一个PhoneNumber类,然后我们会定义一个Address继承自的类,PhoneNumber我曾经说过,我们不能这样做,因为地址不是电话号码,并且要继承,它必须是“是”关系。如:狗是一种动物,我们可以Dog继承自Animal.

但是既然我们必须遵循LSP -- Liskov Substitution Principle,那么“是一个”规则实际上并不是这里的决定因素,因为一个正方形“是一个”矩形(宽度 == 高度),但是 LSP 说我们可以' t 定义一个Square类并从该类继承Rectangle。简单的英文解释,我想,就是对象aRect可以响应消息setWidthAndHeight(w, h),但aSquare不能正确响应,让整个程序正常运行。

如此令人惊讶的是,Address继承类的PhoneNumber类违反了“is a”关系,但并不违反 LSP。那么正式地,它违反了哪些 OOP 原则?

4

2 回答 2

1

首先,这确实违反了LSP。

通常,您不会期望能够用地址替换电话号码。这就是每个人在评论中都在谈论的“常识”。

OOP 理论的要点是,遵循正式规则将使您的类对变化和奇怪的用例等事情具有鲁棒性。即使书中的示例实际上并没有在违反 LSP 的情况下崩溃,我想如果您尝试扩展该类架构,它也会很快崩溃。因此,为避免未来课程出现潜在错误,您应该遵循 LSP - 即使选择不这样做也不会立即破坏任何内容。

其次,它违反了ISP(接口隔离原则)。

这表明类中可用的方法集应该是类对象起作用所需的最小值。

如果 Address 类继承(或可能合理地继承)一堆在处理实际街道地址时从未使用过的 PhoneNumber 方法(例如 getAreaCode() 方法,它对于住宅地址是未定义的),那么它的接口不是最小。

其要点是 OOP 原则实际上只是指导方针。编写违反 SOLID 原则但实际上并没有引入错误的奇怪示例代码绝对是可能的。这并不意味着您正在规避规则;这只是意味着一旦您尝试扩展课程,您就会遇到更多错误。

于 2013-02-26T03:50:13.603 回答
0

使用继承或扩展主要有两个原因。

  1. 重用实现(用于 DRY)
  2. 子类型(LSP 相关)

我不知道所有的原则,但对于你的情况,它违反了@mpm 评论的常识。

因为即使您的代码满足所有原则,它仍然可能是不合适的。换句话说,原则不能涵盖一切。

于 2013-02-25T05:19:14.137 回答