第一章 对象导论
1.5 复用具体实现
-
组合(composition)优先于继承
-
如果组合是动态发生的,则称为聚合(aggregation)
组合经常被视为“has-a”(拥有)关系,就像“汽车拥有引擎”一样。
- 组合关系UML图:
- 组合相较于继承显得灵活性,因此在建立新类时,应该首先考虑组合。
1.6 继承
-
对象可以理解为一种十分方便的工具,是数据和功能的封装。
-
继承关系UML图:
-
经典的几何形例子:每一种都具有额外的特性和行为。
-
子类复制了基类的接口,与基类具有相同的类型👉类型等价性 。导出类如果没有某些具体实现,会直接使用基类接口中的方法,所以说导出类要有自己的实现,这样才有意义,
-
使基类与导出类产生差异的两种方法:
1)直接在导出类中添加新方法:
2)更重要的一种是改变现有基类的方法和行为(覆盖overriding)
![1569465066008](D:\fastwork\Blog\javakam.github.io\files\Java编程思想\1569465066008.png)
1.6.1 “是一个”与“像是一个”关系
is-a 是一个(替代原则==纯粹替代):“一个圆形就是一个几何形状” 。即继承只覆盖基类的方法,而不添加新的方法。
is-like-a 像是一个:导出类添加了新的接口元素,基类中无法访问新添加的方法。比如说空调坏了,改用热力泵制冷,那么这个热力泵就is-like-a空调。
当然,在看过这个设计之后,很显然会发现,制冷系统这个基类不够一般化,应该将其更名为“温度控制系统”,使其可以包括制热功能,这样我们就可以套用替代原则了。这张图说明了在真实世界中进行设计时可能会发生的事情。
使用替代原则设计更好。
1.7 伴随多态的可互换对象
- 面向对象程序设计语言使用了后期绑定的概念。即当对象发送消息时,被调用的代码直到运行时才能确定。c++使用virtual关键字来实现,某些语言默认情况不是动态绑定的,而在Java中动态绑定是默认行为,并不需要添加额外的关键字来实现多态。
void doSomething(Shape shape){
shape.erase();
//...
shape.draw();
}
这个方法可以与任何Shape对话,因此它是独立于任何它要绘制和擦除的对象的具体类型的。当程序中其他地方用到了doSomething()方法:
Circle circle=new Circle();
Triangle triangle=new Triangle();
Line line=new Line();
doSomething(circle);
doSomething(triangle);
doSomething(line);
对doSomething()的调用会自动地正确处理,而不管对象的确切类型。
- 向上转型(upcasting):把导出类看做是它的基类的过程。向上转型是安全的,向下转型==几乎==是不安全的。
1.8 单根继承结构
- 概念:多有的类最终都继承自单一的基类。C++以外所有的OOP语言,Java的终极基类是Object。
- 好处:所有对象都先天具备某些功能,使基本操作更容易,此外,使垃圾回收器的实现变得容易很多,而垃圾回收器也正是Java相对C++的重要改进之一。由于所有对象都具有类型信息,因此不会因为无法确定对象的类型而陷入僵局。这对于系统级操作(如异常处理)显得尤其重要,并且给编程带来了更大的灵活性
-
其他
-
Java完全采用动态内存分配方式
-
并发编程:同一时刻处理多个任务的思想