组合
组合关系概述
- 实现类的复用除了继承外,还可以使用
组合
的方式,把该类当成另一个类的组合成分
,从而允许新类直接复用该类的public方法
。 - 不管继承还是组合,都允许在新类(对于继承就是子类)中直接复用旧类的方法。
- 组合是把
旧类对象作为新类的成员变量
组合起来,用以实现新类的功能
,用户看到的是新类的方法,而不能看到被组合对象的方法。因此,通常要在新类里使用private修饰被组合的旧类对象
。
组合和继承
从类的复用角度看,父类的功能等同于组合中被组合的类,都将自身的方法提供给新类使用;子类和组合关系里的整体类,都可复用原有类的方法,用于实现自身的功能。
继承关系中从多个子类抽象出共有父类的过程,类似于组合关系中多个整体类里提取被组合类的过程;继承关系中从父类派生子类的过程,则类似于组合关系中被组合类组合到整体类的过程。
使用继承实现:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40class Animal
{
private void beat()
{
System.out.println("心脏跳动...");
}
public void breath()
{
beat();
System.out.println("吸一口气,吐一口气,呼吸中...");
}
}
// 继承Animal,直接复用父类的breath()方法
class Bird extends Animal
{
public void fly()
{
System.out.println("我在天空自在的飞翔...");
}
}
// 继承Animal,直接复用父类的breath()方法
class Wolf extends Animal
{
public void run()
{
System.out.println("我在陆地上的快速奔跑...");
}
}
public class InheritTest
{
public static void main(String[] args)
{
Bird b = new Bird();
b.breath();
b.fly();
Wolf w = new Wolf();
w.breath();
w.run();
}
}上述继承关系也可以使用组合实现:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66class Animal
{
private void beat()
{
System.out.println("心脏跳动...");
}
public void breath()
{
beat();
System.out.println("吸一口气,吐一口气,呼吸中...");
}
}
class Bird
{
// 将原来的父类组合到原来的子类,作为子类的一个组合成分
private Animal a;
public Bird(Animal a)
{
this.a = a;
}
// 重新定义一个自己的breath()方法
public void breath()
{
// 直接复用Animal提供的breath()方法来实现Bird的breath()方法。
a.breath();
}
public void fly()
{
System.out.println("我在天空自在的飞翔...");
}
}
class Wolf
{
// 将原来的父类组合到原来的子类,作为子类的一个组合成分
private Animal a;
public Wolf(Animal a)
{
this.a = a;
}
// 重新定义一个自己的breath()方法
public void breath()
{
// 直接复用Animal提供的breath()方法来实现Wolf的breath()方法。
a.breath();
}
public void run()
{
System.out.println("我在陆地上的快速奔跑...");
}
}
public class CompositeTest
{
public static void main(String[] args)
{
// 此时需要显式创建被组合的对象
Animal a1 = new Animal();
Bird b = new Bird(a1);
b.breath();
b.fly();
// 此时需要显式创建被组合的对象
Animal a2 = new Animal();
Wolf w = new Wolf(a2);
w.breath();
w.run();
}
}
何时使用组合或者继承
组合
是“有 has-a
”关系,继承
是“是 is-a
”关系。- 比如
Dog和Animal类
应该使用继承
关系,因为用一个动物组合成一个狗毫无意义,狗不是由动物组成的,反而狗是动物(is-a关系)
; - 比如
Person类和Head类
就应该使用组合
关系,因为一个人由头组合(has-a关系)
,而不是头是人。
- 比如