目录
抽象类 vs. 接口的联系与区别
联系
- 都可以用于定义抽象行为,不能直接实例化,必须由子类或实现类提供具体实现。
- 都可以包含方法,供子类或实现类继承或实现。
- 都支持多态,可以通过父类引用指向子类对象(向上转型)。
区别
对比项 | 抽象类(Abstract Class) | 接口(Interface) |
---|---|---|
关键字 | abstract class | interface |
方法 | 既可以有抽象方法,也可以有非抽象方法(普通方法) | Java 8+ 以前只能有抽象方法,Java 8+ 允许 default 和 static 方法 |
属性 | 允许定义变量,可以有private 、protected 、public | 只能定义 public static final (常量),不能有普通变量 |
构造方法 | 可以有构造方法 | 不能有构造方法 |
继承关系 | 只能继承一个抽象类(单继承) | 可以实现多个接口(多实现) |
默认权限 | 抽象方法默认 protected 或 public | 方法默认 public |
使用场景 | 适用于具有共同行为和属性的类 | 适用于定义行为规范,不关心具体实现 |
代码示例
抽象类示例
abstract class Animal {
String name;
// 抽象方法(子类必须实现)
abstract void makeSound();
// 具体方法(子类可以直接使用或重写)
void sleep() {
System.out.println(name + " is sleeping.");
}
}
class Dog extends Animal {
Dog(String name) {
this.name = name;
}
@Override
void makeSound() {
System.out.println("Woof! Woof!");
}
}
接口示例
interface Flyable {
int MAX_SPEED = 100; // 默认 public static final
void fly(); // 默认 public abstract 方法
default void land() {
System.out.println("Landing safely.");
}
}
class Bird implements Flyable {
@Override
public void fly() {
System.out.println("Bird is flying.");
}
}
何时使用?
- 使用抽象类:当多个类之间有共同的状态(字段)和部分相同的行为,建议使用抽象类。例如:
Animal
(动物)拥有name
属性和sleep()
方法,所有动物共享这些特性。 - 使用接口:当多个类之间只有行为上的共性,但不需要共享状态时,建议使用接口。例如:
Flyable
仅定义“能飞”这一能力,不关心实现。
如果一个类既有共同的状态(属性)又要实现多个行为(功能),可以结合抽象类和接口:
abstract class Vehicle {
String brand;
abstract void drive();
}
interface Electric {
void charge();
}
class Tesla extends Vehicle implements Electric {
@Override
void drive() {
System.out.println("Tesla is driving.");
}
@Override
public void charge() {
System.out.println("Tesla is charging.");
}
}
总结
- 抽象类 = “是什么” + “能做什么”(有状态 + 行为)
- 接口 = “能做什么”(纯行为)
如果是多个类的共同父类,用抽象类;如果是不同类共享的一组行为,用接口! 🚀