在 Java(以及面向对象设计)中,“用组合而不是继承”(Favor Composition over Inheritance)是一个非常经典的设计原则。下面从原因、对比、例子、适用场景几个方面说明,为什么 Java 中更推荐用组合。
组合:一个类把另一个类的对象作为自己的成员变量来使用。
class Engine {
void run() {}
}
class Car {
private Engine engine = new Engine();
void start() {
engine.run();
}
}
Car 拥有 Engine,而不是 Car 是 Engine。
继承是 白盒复用:
class Animal {
void eat() {}
}
class Dog extends Animal {}
一旦 Animal 改了实现,Dog 可能受影响。
✅ 组合是 黑盒复用,只依赖接口/方法,不关心实现。
Java 不支持多继承:
class A {}
class B {}
class C extends A, B {} // ❌ 编译错误
但组合可以“拥有多个”:
class C {
A a;
B b;
}
用继承表达所有关系:
Animal
├── Bird
│ ├── FlyingBird
│ │ ├── Sparrow
│ │ └── Eagle
│ └── NonFlyingBird
✅ 组合可以避免:
class Bird {
FlyBehavior fly;
}
组合支持运行时动态变化:
class Car {
Engine engine;
void setEngine(Engine e) {
this.engine = e;
}
}
继承在编译时就固定了。
| 关系 | 用 |
|---|---|
| is-a | 继承 |
| has-a | 组合 |
❌ 错误使用继承:
class Person extends List<String> {}
✅ 正确:
class Person {
List<String> names;
}
interface FlyBehavior {
void fly();
}
class FlyWithWings implements FlyBehavior {
public void fly() {}
}
class Duck {
FlyBehavior flyBehavior;
void performFly() {
flyBehavior.fly();
}
}
✅ 不用改 Duck 类,就能换飞行方式
✅ 适合用继承的情况:
is-a例如:
class ArrayList extends AbstractList
Java 用组合,是为了降低耦合、提高灵活性、避免继承的局限性。
原则记住:
能组合,就别继承;
真 is-a,才用继承。
如果你愿意,我也可以结合 Spring / 实际项目 / 面试角度再讲一遍。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。