书接上回Java继承讲解(第三节)继承关系上的代码块执行顺序-CSDN博客
1. 继承(Inheritance)
1.1 继承的定义
继承是一种"是一个"**(is-a)的关系,指的是子类继承父类的属性和方法,子类可以扩展或重写父类的功能。继承通过 extends
关键字实现。
1.2 继承的优点
- 代码复用:子类继承父类的属性和方法,避免重复编写相同的代码。
- 方法重写:子类可以根据自身的需要,重写父类的方法,增强代码的扩展性。
- 多态性:继承关系能够实现多态,允许子类对象通过父类引用来调用方法,实现动态绑定。
1.3 继承的示例
class Animal {
public void eat() {
System.out.println("动物正在吃东西");
}
}
class Dog extends Animal {
public void bark() {
System.out.println("狗在叫");
}
}
public class Main {
public static void main(String[] args) {
Dog dog = new Dog();
dog.eat(); // 子类可以继承父类的eat方法
dog.bark(); // 子类自己扩展的方法
}
}
1.4 继承的缺点
- 继承是静态的:一旦子类继承了父类,就形成了一种强耦合关系,子类的行为依赖于父类的实现。如果父类发生变化,子类的行为也可能受到影响。
- 滥用继承:如果继承层次过深,会导致系统复杂且难以维护。修改父类会对整个继承链产生影响。
2. 组合(Composition)
2.1 组合的定义
组合是一种"有一个"(has-a)的关系,指的是一个类通过拥有另一个类的实例来使用它的功能。组合意味着类之间是关联关系**,而不是继承关系。通过组合,可以更灵活地构建类的行为。
2.2 组合的优点
- 松耦合:组合使类与类之间的关系更松散,不同类的功能是通过对象关联而不是继承,修改某个类不会影响其他类。
- 运行时动态替换:组合允许在运行时替换对象的行为,因为组合的类可以通过接口或者对象引用动态组合不同的实现。
- 灵活性:相比继承,组合更灵活,它允许你根据需要组合不同的类,而不必在类的设计阶段决定继承层次。
2.3 组合的示例
class Engine {
public void start() {
System.out.println("引擎启动");
}
}
class Car {
private Engine engine; // 组合关系
public Car() {
engine = new Engine(); // Car"有一个"Engine
}
public void drive() {
engine.start();
System.out.println("汽车正在行驶");
}
}
public class Main {
public static void main(String[] args) {
Car car = new Car();
car.drive(); // 组合方式下的行为调用
}
}
2.4 组合的缺点
- 可能增加代码复杂性:由于需要手动创建和管理组合对象的实例,有时候组合可能导致代码更加复杂。
- 无法直接复用父类方法:与继承不同,组合无法直接使用被组合类的所有方法。如果需要复用某些行为,必须显式调用相应的方法。
3. 继承 vs. 组合
特性 | 继承(Inheritance) | 组合(Composition) |
---|---|---|
关系类型 | "是一个"(is-a) | "有一个"(has-a) |
耦合性 | 强耦合(子类与父类紧密相关) | 松耦合(类之间关联关系松散) |
代码复用 | 通过继承父类的方法和属性来复用代码 | 通过组合其他对象来实现功能复用 |
灵活性 | 继承层次一旦确定,不易修改 | 组合灵活,可以在运行时动态替换行为 |
修改影响 | 父类的修改可能影响所有子类 | 类的修改不会影响其他类 |
实现复杂度 | 相对简单,继承链清晰 | 可能需要管理多个对象,增加复杂性 |
4. 组合与继承的结合使用
在实际开发中,继承和组合并不冲突,很多时候可以结合使用,以达到最佳效果。你可以使用继承来表达类之间的通用行为,然后使用组合来提供额外的功能。
示例:结合使用继承与组合
class Engine {
public void start() {
System.out.println("引擎启动");
}
}
class Vehicle {
public void move() {
System.out.println("车辆移动");
}
}
class Car extends Vehicle {
private Engine engine;
public Car() {
this.engine = new Engine();
}
@Override
public void move() {
engine.start(); // 使用组合提供额外的功能
super.move(); // 继承父类的通用行为
}
}
public class Main {
public static void main(String[] args) {
Car car = new Car();
car.move(); // 既调用了父类方法,又使用了组合的Engine功能
}
}
解释:
Car
类继承了Vehicle
类,使用了父类的move()
方法来表示车辆移动的通用行为。- 同时,
Car
类通过组合Engine
对象,增加了引擎启动的功能。这种组合和继承的结合使用增强了类的灵活性和功能扩展性。