9.1继承关系--继承财富,更要继承责任
预览
1.接口继承不是为了代码重用,而是为了代码被重用。
2.实现继承消费可重用旧代码,接口继承生产可重用的新代码
3.不要问系统能为你做些什么,而要问你能为系统做些什么
4.与其说继承是一种is-a或is-a-kind-of的关系,不如说继承是一种behaves-like-a或is-substitutalbe-for的关系
1.在UML中,通常用用泛化generalization来表达继承关系,从逻辑上说,比继承更准确,更确切的说:泛化强调的是概念
关系,而继承强调的是语言机制
2.UML恰恰侧重于设计,事实上,人们常常会从设计的一些类中提炼出共同的特征,并放在新建类中,此时父类是后于子类
设计的或许称作超类更合适些,换言之,从子类到超类的泛化,是一种概念抽象的过程,从超类到子类的特化,是一种概念
细化的过程,两种过程在设计中往往是交替采用的,这也就是前面提到的5类基本抽象之一的类型层级
3.接口继承
唯一的理由是,此类希望以该接口的形式为人所用,也就是说,接口继承不是而为了代码重用,而是为了代码被重用,虽然
最终都是重用,但主客关系倒置。再明确些,实现继承消费可重用的旧代码,接口继承生产可重用的新代码。一个是重视权利
的索取型的。一个是重视义务的奉献型。OOp更提倡后者,倒不是因为它更讲道德,而是因为它多采取子从底到上的方式
。试想,如果代码都倾向于重用而不是被重用,做顶不做底,那系统还不得头重脚轻。会用不与被用。不要问系统能为你
做些什么,而要问你能为系统做些什么。
4.继承也被称为子类化,接口继承进而被称为子类型化。子类型的关键是可替换性。具体地说。类型A的子类型B应该满足
以下条件:将程序中类型A的对象置换为B的对象,不会影响程序的合理性和正确性。
5.里氏代换原则的本质是为了保证规范抽象。
规范抽象:使用者与实现者之间的一种契约,是代码的功能和实现相分离
6.接口继承在遵循里氏代换原则的前提下,通过接口重用达成规范重用,保证了多态抽象,进而维护了开闭原则,让客户
一劳永逸地享受接口服务。
7.实现继承和接口继承都应该遵守里氏代换原则。这既是一种义务,也是一种权益,说是义务。是因为实现继承
在继承实现的同时也继承接口。按理也应该继承接口规范。说是权益。是因为接口的继承能让代码被重用。如果只是为了
重用积基类的代码,并不希望重用他的接口,那就应该采用合成。
8继承关系在于可代换性。即遵循接口的规范表面一个子类型的行为表现如超类型
9.正方形继承矩形
其实矩形也有错,错在没有明确地描述规范。比如,应当在setWidth中声明:在设置宽度的时赢保持高度不变。这也就是
我们在讨论契约式时提到的后验条件。如果矩形类有此契约在先,也许正方形不会选择继承
当然,企业继承鸟,正方形继承矩形,圆继承椭圆的做法究竟是否合理。最终取决于实际需求和具体规范,不能一概而论
10.归根到底,继承还是不继承,在实际编程中,体型类型的概念和他的行为规范,而不是它的命令名所引起的认知,毕竟
,软件是运行在电脑中的代码,而不是运行在人脑中的思维。总而言之,概念抽象只是手段,规范抽象才是目的。
11.任何类型都应该保持或强化起超类型的规范。绝不能弱化规范。用通俗的语言来说。要求只能更少。承诺之恩给你更多。
用契约式设计的语言。先验条件只能弱化后验条件和类不变量只能强化。
12.里氏代换原则是基于类型的,简而言之,类偏执语法,强调实现方式,类型偏执语义。强调行为方式,再简要些,类是
实现,类型是接口
13.一个作为抽象数据类型的类,通过数据抽象和封装机制而被化分为接口和实现。此时的接口就是人们常说的API,是类向
外提供服务的窗口。
另一方面,一个类有可以通过多态抽象和继承机制而拥有抽象类型,抽象类型是接口,类是实现。
第一种方式:在语义上通过数据抽象得到了API接口,在语法上通过封装机制隐藏private实现
第二种方式:在语义上通过多态抽象得到interface接口。在语法上通过继承机制隐藏实现