一、抽象的概念
抽象是一种通过创建简化的模型,来分离 "做什么" 与 "如何做" 的软件设计思想。
Java通过抽象类和接口来实现抽象:
- 抽象类(Abstract Class):使用 abstract 关键字声明。
- 接口(Interface):使用 interface 关键字声明。
二、抽象类
1. 抽象类的概念
抽象类是一种用于表示抽象概念的类,它不能被实例化,只能被继承。抽象类通过抽象方法强制子类实现特定行为,同时通过具体方法让子类共享共同行为,在规范性与复用性之间取得平衡。
2. 抽象类的要点
- 抽象类不能被实例化,因为它代表的是不完整的抽象概念。
- 抽象类用于被其他类继承。
- 子类继承抽象类后,必须实现所有的抽象方法,否则该子类也必须声明为抽象类。
- 抽象类可以包含构造方法,这些构造方法在子类实例化时被调用。
- 抽象类还可以包含成员变量、成员方法、静态变量和静态方法。
3. 代码示例
java
abstract class Animal {
// 成员变量
protected String name;
private static int animalCount = 0; // 静态变量(第5点)
// 构造方法
public Animal(String name) {
this.name = name;
animalCount++;
}
// 抽象方法
public abstract void makeSound();
// 具体方法
public void sleep() {
System.out.println(name + "正在睡觉");
}
// 静态方法
public static int getAnimalCount() {
return animalCount;
}
}
// 子类必须实现所有抽象方法
class Dog extends Animal {
// 调用父类构造方法
public Dog(String name) {
super(name);
}
@Override
public void makeSound() {
System.out.println(name + "汪汪叫");
}
}
// 测试
public class Main {
public static void main(String[] args) {
// Animal animal = new Animal("抽象动物"); // 编译错误,抽象类不能被实例化
Animal dog = new Dog("小黑");
dog.makeSound();
dog.sleep();
System.out.println("动物数量: " + Animal.getAnimalCount());
}
}
三、接口
1. 接口的概念
接口不代表一类事物,而是代表一种规则,是对行为能力的抽象。
实际上,接口定义了一个类必须实现的方法集合。这些方法在接口中没有具体的实现,必须由实现该接口的类来实现。一个类可以实现多个接口。
2. 接口的要点
- 接口定义方法契约,实现类必须提供这些方法的具体实现。
- 一个类可以实现多个接口,获得多种行为能力。
- 接口中的方法默认是 public abstract 的。
- 接口主要用于定义对象的能力和角色,而非 is-a 关系。
3. 代码示例
java
// 定义能力接口
interface Flyable {
void fly();
}
interface Swimmable {
void swim();
}
// 不同的类实现相同接口
class Bird implements Flyable {
@Override
public void fly() {
System.out.println("鸟飞行");
}
}
class Duck implements Flyable, Swimmable {
@Override
public void fly() {
System.out.println("鸭子飞行");
}
@Override
public void swim() {
System.out.println("鸭子游泳");
}
}
// 使用接口实现多态
public class Test {
public static void makeItFly(Flyable flyable) {
flyable.fly(); // 不关心具体类型,只关心飞行能力
}
public static void makeItSwim(Swimmable swimmable) {
swimmable.swim();
}
public static void main(String[] args) {
// 创建不同类型的对象
Bird sparrow = new Bird();
Duck donald = new Duck();
makeItFly(sparrow);
makeItFly(donald);
makeItSwim(donald);
}
}
四、抽象类与接口应用场景对比
使用抽象类:
- 需要一个共同的基类,部分方法需要在子类中实现,部分方法已经有具体实现。
- 需要包含成员变量和构造方法,维护一定的状态。
使用接口:
- 需要定义一个公共的协议或契约,方法的具体实现由不同的类负责。
- 需要一个类实现多个不同的方法集合。