一、从现实到代码:抽象的概念¶
想象一下,我们去动物园看到各种动物:猫、狗、鸟。它们都属于“动物”这个大类,有共同的特征(比如会呼吸、有生命),但具体行为不同(猫“喵喵”叫,狗“汪汪”叫,鸟“喳喳”叫)。
在Java中,我们可以把“动物”抽象成一个模板,这个模板包含所有动物的共同特征(比如“会叫”),但不具体实现“怎么叫”——因为不同动物叫的方式不一样。这个模板就是抽象类,而“怎么叫”就是抽象方法(只定义“要做什么”,不定义“怎么做”)。
二、为什么要定义抽象类?¶
抽象类的核心作用是提供通用模板,同时限制子类必须实现某些方法。具体来说有3个原因:
- 统一行为规范:比如所有动物都要“叫”,抽象类规定“必须有叫的方法”,子类不能随便省略,保证代码风格一致。
- 避免不完整对象:抽象类本身不能直接创建对象(比如“动物”本身不存在,只有具体的猫、狗才存在),强制子类去实现细节,避免创建功能缺失的对象。
- 代码复用:抽象类可以包含通用属性和方法(比如所有动物都有“年龄”属性,“吃饭”方法),子类直接继承,不用重复写代码。
三、基础语法解析¶
1. 定义抽象类¶
用 abstract 关键字修饰类,语法格式:
abstract class 类名 {
// 抽象方法(只声明,无实现)
public abstract void 方法名();
// 非抽象方法(可以有具体实现)
public void 通用方法() {
System.out.println("这是通用方法");
}
}
注意:
- 抽象类可以有普通属性(比如 int age;)和非抽象方法。
- 抽象类不能被 new 直接实例化(比如 new 抽象类名() 是错误的),只能被子类继承。
2. 定义抽象方法¶
用 abstract 关键字修饰方法,语法格式:
public abstract void 方法名(); // 只有声明,没有大括号和具体逻辑
注意:
- 抽象方法必须由子类实现(除非子类也是抽象类)。
- 抽象方法不能是 private(子类无法访问私有方法),也不能是 static(static 方法属于类,而抽象方法无实现,矛盾)。
3. 子类继承抽象类¶
子类必须实现抽象类中所有的抽象方法,否则子类也必须声明为抽象类。语法示例:
// 抽象类:动物
abstract class Animal {
public abstract void makeSound(); // 抽象方法:叫什么声(未实现)
public void eat() { // 非抽象方法:吃饭(具体实现)
System.out.println("动物在吃饭");
}
}
// 子类:狗(继承Animal)
class Dog extends Animal {
// 必须实现抽象方法makeSound()
@Override
public void makeSound() {
System.out.println("汪汪汪!");
}
}
// 子类:猫(继承Animal)
class Cat extends Animal {
@Override
public void makeSound() {
System.out.println("喵喵喵!");
}
}
四、示例代码:用抽象类实现“动物叫”¶
// 抽象类:动物
abstract class Animal {
// 抽象方法:规定子类必须实现“叫”的行为
public abstract void makeSound();
// 非抽象方法:所有动物都会吃饭(通用实现)
public void eat() {
System.out.println("动物正在吃饭");
}
}
// 子类:狗
class Dog extends Animal {
@Override
public void makeSound() {
System.out.println("狗:汪汪汪!");
}
}
// 子类:猫
class Cat extends Animal {
@Override
public void makeSound() {
System.out.println("猫:喵喵喵!");
}
}
// 测试类
public class TestAnimal {
public static void main(String[] args) {
// 只能通过子类实例化(抽象类不能直接new)
Animal dog = new Dog();
Animal cat = new Cat();
dog.makeSound(); // 输出:狗:汪汪汪!
cat.makeSound(); // 输出:猫:喵喵喵!
dog.eat(); // 输出:动物正在吃饭(继承通用方法)
}
}
五、关键点总结¶
- 抽象类定义:用
abstract class声明,不能实例化。 - 抽象方法:用
abstract声明,无方法体,子类必须实现。 - 子类规则:非抽象子类必须实现所有抽象方法;抽象子类可继承抽象方法。
- 通用方法:抽象类可包含普通方法和属性,子类直接复用。
小提醒:抽象类是“单继承”的,子类只能继承一个抽象类,但可以实现多个接口(后续会学)。如果需要强制子类实现某方法,抽象类是更灵活的选择!