对于继承可能会引发某种争论:继承应该只重载基类的方法(而并不添加在基类中没有的新
方法)吗?如果这样做,就意味着导出类和基类是完全相同的类型,因为它们具有完全相同
的接口。结果你可以用一个导出类对象来完全替代一个基类对象。这可以被视为“纯粹替代
(pure substitution)”,通常称之为“替代法则(substitution principle)”。在某种意义上,这
是一种处理继承的理想方式。我们经常将这种情况下的基类与导出类之间的关系称为“is-a”
关系,因为你可以说“一个圆形就是一个几何形状”。判断是否继承,就是要确定你是否可
以用 is-a 来描述类之间的关系,并使之具有实际意义。
有时你必须在导处类型中添加新的接口元素,这样也就扩展了接口并创建了新的类型。这个
新的类型仍然可以替代基类,但是这种替代并不完美,因为基类无法访问你新添加的方法。
这种情况我们可以描述为“is-like-a”关系。新类型具有旧类型的接口,但是它还包含其他
方法,所以你不能说它们完全相同。以空调为例,假设你的房子里已经布线安装好了所有的
冷气设备的控制器,也就是说,你的房子具备了让你控制冷气设备的接口。想象一下,如果
空调坏了,你用一个既能制冷又能制热的热力泵替换了它,那么这个热力泵就“is-like-a(像
是一个)”空调,但是它可以做更多的事。因为你的房子的控制系统被设计为只能控制冷气
设备,所以它只能和新对象中的制冷部分进行通信。尽管新对象的接口已经被扩展了,但是
现有系统除了源接口之外,对其他东西一无所知。
当然,在你看过这个设计之后,你会发现很显然,Cooling System 这个基类不够一般化,应
该将其更名为“温度控制系统”,使其可以包括制热功能,这样我们就可以套用替代法则了。
这张图说明了在真实世界中进行设计时可能会发生的事情。
当你看到替代法则时,很容易会认为这种方式“纯粹替代”是唯一可行的方式,而且事实上
言此方式,你的设计会显得很好。但是你会发现有时同样很明显你必须在导处类接口中添加
新方法。只要仔细审视,两种方法的使用场合应该是相当明显的。