Go中有接口的概念而c++中有抽象类的概念,这两者有什么具体的区别呢?
1 接口vs抽象类
1.1 实现一个有Run方法的接口
先来看Go的接口的一个例子
1 | type Run interface{ |
1.1 实现一个有Sound方法和s(sound声音)属性的抽象类
1 |
|
1.3 一个小问题
提问: 假如1.1用抽象类来实现的话,接口应该叫什么?
1.4 一点思考
假设: A为接口/抽象类, B C为实现了接口/继承了抽象类的数据类型
接口更多描述的是 B is like A, C is like A, 是对B C类型的一个行为的抽象,所以接口中没有属性只有方法(不懂Java不过Java中貌似可以有静态成员)
而抽象类更多描述的是 B is A, C is A, 是对B C的一个对类型的复用/抽象,描述了类型本质的属性和方法
人可以跑,车可以跑,跑可以作为人和车的一个接口,描述了人和车的跑的行为1
2
3type Run interface {
run()
}
猫和狗都有独自的声音,都可以发出声音1
2
3
4
5class Animal {
public:
Sound s;
void sound();
}
人和车的相同本质并不是都会跑,而是都具有跑的行为罢了
猫和狗相同本质的是都为动物
不要为了复用代码而随意制造抽象类,比如因为车和人都可以跑,就抽象出一个不知道是什么的抽象类
2 组合vs继承
2.1 组合
组合是通过成员实例引用不同的类型来实现抽象
例子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
31class Animal {
Animal(Sound* s_) : s(s_) {}
Sound* s; // 用Sound对象组成
void sound() {
s->sound();
}
};
class Sound {
public:
voice v;
virtual void sound() = 0;
}
class CatSound : public Sound{
CatSound(voice v_): v(v_) {}
virtual void sound() {
std::cout << v << v << v;
};
};
class DogSound : public Sound{
DogSound(voice v_): v(v_) {}
virtual void sound() {
std::cout << v;
};
};
int main() {
Animal a0(new CatSound);
Animal a1(new DogSound);
}
2.2 继承
1 | class Animal { |
2.3 对比
2.2继承中现在子类依赖父类[耦合], 导致父类的修改引起子类爆炸
2.1组合中则不会有这种问题,因为Animal与Sound是耦合度很低的[保持接口不变的情况下]