目录
1. 前言
2016 年 8 月我去面试 Android 的时候,遇到一个 Java 大牛,问过我这个问题。我确实不知道类与类之间竟然会有 6 种关系。面试后,虽然查了一下,但是依然不理解:类与类之间这 6 种关系是怎么总结出来的。
2. 正文
2.1 继承(generalization)
这个大家都不陌生,可以说是非常熟悉了。使用继承,我们能够以现有类为基础(获取它的全部可继承的成员),通过添加或修改一些成员来创建新类。源类常被称为基类、超类或者父类,导出类常被称为继承类或者子类。以经典的几何形的例子来说明:
Shape 类是父类,而 Circle、Square、Triangle 是三个子类,通过继承子类获得了父类的全部可继承的成员。
但是,子类难道仅仅是为了获取父类的全部可继承的成员而已吗?
显然不是,如果仅仅那样,何不直接使用父类呢?
子类通常会和父类产生差异,有两种办法可以实现。
第一种产生差异的办法是直接在子类中添加新的方法(这些新方法并不是父类的方法),这样就扩展了接口,这种情况下子类和父类是 is-like-a(像是一个)关系。
第二种产生差异的办法是改变现有父类的方法的行为(这被称为覆盖 override),这种情况下子类和父类是 is-a(是一个)关系。替代原则适用于这种情况。
2.2 实现(realization)
这是类与接口之间的关系。注意类实现接口,需要用到的是 implements
关键字。下边使用 Java 编程思想中的例子说明:
代码如下:
interface Instrument {
void play();
String what();
void adjust();
}
class Wind implements Instrument {
@Override
public void play() {
System.out.println("Wind " + "play()");
}
@Override
public String what() {
return "Wind what()";
}
@Override
public void adjust() {
System.out.println("Wind " + "adjust()");
}
}
class Percussion implements Instrument {
@Override
public void play() {
System.out.println("Percussion " + "play()");
}
@Override
public String what() {
return "Percussion what()";
}
@Override
public void adjust() {
System.out.println("Percussion " + "adjust()");
}
}
class Stringed implements Instrument {
@Override
public void play() {
System.out.println("Stringed " + "play()");
}
@Override
public String what() {
return "Stringed what()";
}
@Override
public void adjust() {
System.out.println("Stringed " + "adjust()");
}
}
2.3 依赖(dependency)
依赖关系是一种使用关系。如果一个类A通过new关键字创建了另一个类B的实例, 那么独立于类B去使用或者测试类A是不行的. 这时, 类A和类B就存在dependency. 类A被叫做dependant, 类B被叫做 dependency. A dependant depends on its dependencies, 在这里, 类A依赖于类B。依赖可以理解为耦合。
依赖确实是有缺点的:代码复用性差,难以测试,难以维护。
依赖的分类:类依赖,接口依赖,方法/属性依赖,直接或间接的依赖。
2.4 关联(association)
表示两个不相关的对象之间的关系。两个单独的类通过它们的对象发生关联。两个类是不相关的,也就是说一个类可以单独存在在另外一个类不存在的情况下。可以是一对一、一对多、多对一、一对一的关系。
2.5 聚合(aggregation)
聚合是关联的一种。如果组合是动态发生的,通常被称为聚合(aggregation)。聚合是一种弱的“拥有”关系,它体现的是 A 对象包含 B 对象,但 B 对象并不是 A 对象的一部分。比如车队里包含有多个车,人群里包含有多个人。它只是一种单方向的关系,比如车队包含车,但车并不包含车队。
2.6 组合(composition)
使用现有的类合成新的类,这就是组合(composition)。组合经常被视为“has-a”(拥有)关系,组合是一种强的“拥有”关系,体现的是严格的部分和整体的关系,部分和整体的生命周期是一样的(整体离不开部分,部分也离不开整体)。比如汽车拥有引擎,人拥有腿。在 UML 图中,使用实心菱形来表示组合关系。
组合非常直观,只需要在新类中产生现有类的对象,这样新的类就由现有类的对象所组成。组合只是复用了现有代码的功能,而不是现有代码的形式。
使用代码表示如下:
public class Car {
private Engine mEngine;
}
class Engine {
}
public class Person {
private Leg mLeg;
}
class Leg {
}
3. 最后
简单地介绍了一下类与类之间的 6 种关系,希望能够帮助到大家。