Java的类和类之间存在多种关系,总的可以分为继承(泛化)、关联、依赖。其中关联关系又可以细分为组合和聚合关系。
泛化
也就是继承关系,即存在 is - a 关系,在Java中常用extends关键字来实现。
举例:
class animal{
}
//实现类的继承
public class cat extends animal{
}
Java中继承能够实现代码重用,但是它不是代码重用的最好形式,因为继承会打破封装,提高代码的耦合度。上层类的实现有可能随着发行版本的不同而有所变化(比如添加了新方法),这时下层可能被“打破”,即使下层类的代码没有改变。
依赖
依赖(Dependency)关系是类与类之间的联接。依赖关系表示一个类依赖于另一个类的定义。例如,一个人(Person)可以买车(car)和房子(House),Person类依赖于Car类和House类的定义,因为Person类引用了Car和House。与关联不同的是,Person类里并没有Car和House类型的属性,Car和House的实例是以参量的方式传入到buy()方法中去的。一般而言,依赖关系在Java语言中体现为局域变量、方法的形参,或者对静态方法的调用。
class Car{
public static void run(){
}
}
class Driver{
//使用形参方式发生依赖关系
public void drive1(Car car){
car.run();
}
//使用局部变量发生依赖关系
public void drive2(){
Car car=new Car();
car.run();
}
//使用静态变量发生依赖关系
public void drive3(){
car.run();
}
}
依赖是一种耦合度最弱的关系,上述例子中Driver类依赖于Car类。
关联
关联(Association)关系是类与类之间的联接,它使一个类知道另一个类的属性和方法。关联可以是双向的,也可以是单向的。在Java语言中,关联关系一般使用成员变量来实现。
class Driver{
Car mycar;
//使用成员变量形式实现关联
public void drive(){
mycar.run();
}
}
关联关系是比依赖更加强的一种关系。
聚合
聚合(Aggregation) 关系是关联关系的一种,是强的关联关系。聚合是整体和个体之间的关系。例如,公司类与员工类。与关联关系一样,聚合关系也是通过实例变量实现的。但是关联关系所涉及的两个类是处在同一层次上的,而在聚合关系中,两个类是处在不平等层次上的,一个代表整体,另一个代表部分。聚合是一种 has-a 的关系。
聚合可以是空的。还是公司类和员工类,当一个公司没有员工的时候,它还是一个公司,只不过是一个空壳公司。和组合的整体和部分的关系相比较,聚合是一种不具有“唇亡齿寒、存亡与共”的关系的。
class Driver {
//使用成员变量形式实现聚合关系
Car mycar;
public void drive(){
mycar.run();
}
}
聚合关系一般使用setter方法给成员变量赋值。
组合
组合(Composition) 关系是关联关系的一种,是比聚合关系强的关系。它要求普通的聚合关系中代表整体的对象负责代表部分对象的生命周期,组合关系是不能共享的。代表整体的对象需要负责保持部分对象和存活,在一些情况下将负责代表部分的对象湮灭掉。代表整体的对象可以将代表部分的对象传递给另一个对象,由后者负责此对象的生命周期。换言之,代表部分的对象在每一个时刻只能与一个对象发生组合关系,由后者排他地负责生命周期。部分和整体的生命周期一样。
class Driver{
Car mycar;
public Driver(Car car){
mycar = car;
}
}
组合关系更多的可能使用构造方法来达到初始化的目的。上述提到的相比继承,更多的时候可以选择组合或者聚合来替代,通过关联的方式,原来想要继承的类编程了新类的一个组成部分。新类中的每一个实例方法都可以调用被包含的已有类实例中对应的方法,并返回它的结果,这种行为称为转发(forwarding),新类中的方法被称为转发方法。
总结:
- 关联、聚合和组合只能配合语义,结合上下文才能判断出来,很多时候,他们的代码可能类似甚至一样。
- 只有当下层类和上层类之间确实存在继承关系时,使用继承才是正确的。
参考资料:
http://www.importnew.com/15490.html 《Java面向对象编程》,作者:孙卫琴