Java抽象类详解:定义、继承与使用
Java抽象类详解:定义、继承与使用
概述
抽象类(Abstract Class)是不能被实例化的类,用于定义一组相关类的共同特征。抽象类可以包含抽象方法和普通方法,是实现多态和代码复用的重要机制。
1. 抽象类的定义
基本语法
public abstract class Animal {
protected String name;
protected int age;
// 构造方法
public Animal(String name, int age) {
this.name = name;
this.age = age;
}
// 抽象方法(没有方法体)
public abstract void sound();
public abstract void move();
// 普通方法(有方法体)
public void eat() {
System.out.println(name + "正在吃东西");
}
public void sleep() {
System.out.println(name + "正在睡觉");
}
public void display() {
System.out.println("名字: " + name + ", 年龄: " + age);
}
}
// 抽象类不能被实例化
// Animal animal = new Animal("Tom", 3); // 编译错误
2. 继承抽象类
public class Dog extends Animal {
private String breed;
public Dog(String name, int age, String breed) {
super(name, age); // 调用父类构造方法
this.breed = breed;
}
@Override
public void sound() {
System.out.println(name + "汪汪汪");
}
@Override
public void move() {
System.out.println(name + "跑来跑去");
}
public void fetch() {
System.out.println(name + "正在捡球");
}
@Override
public void display() {
super.display();
System.out.println("品种: " + breed);
}
}
public class Cat extends Animal {
public Cat(String name, int age) {
super(name, age);
}
@Override
public void sound() {
System.out.println(name + "喵喵喵");
}
@Override
public void move() {
System.out.println(name + "轻手轻脚地走");
}
public void scratch() {
System.out.println(name + "正在抓老鼠");
}
}
// 测试
public class AbstractClassTest {
public static void main(String[] args) {
Dog dog = new Dog("旺财", 3, "金毛");
Cat cat = new Cat("咪咪", 2);
dog.display();
dog.sound();
dog.move();
dog.eat();
dog.fetch();
System.out.println();
cat.display();
cat.sound();
cat.move();
cat.eat();
cat.scratch();
}
}
3. 抽象类与多态
public abstract class Shape {
protected String name;
public Shape(String name) {
this.name = name;
}
// 抽象方法
public abstract double area();
public abstract double perimeter();
// 普通方法
public void display() {
System.out.println("形状: " + name);
System.out.println("面积: " + String.format("%.2f", area()));
System.out.println("周长: " + String.format("%.2f", perimeter()));
}
}
public class Circle extends Shape {
private double radius;
public Circle(double radius) {
super("圆形");
this.radius = radius;
}
@Override
public double area() {
return Math.PI * radius * radius;
}
@Override
public double perimeter() {
return 2 * Math.PI * radius;
}
}
public class Rectangle extends Shape {
private double width;
private double height;
public Rectangle(double width, double height) {
super("矩形");
this.width = width;
this.height = height;
}
@Override
public double area() {
return width * height;
}
@Override
public double perimeter() {
return 2 * (width + height);
}
}
public class Triangle extends Shape {
private double a, b, c;
public Triangle(double a, double b, double c) {
super("三角形");
this.a = a;
this.b = b;
this.c = c;
}
@Override
public double area() {
double s = (a + b + c) / 2;
return Math.sqrt(s * (s - a) * (s - b) * (s - c));
}
@Override
public double perimeter() {
return a + b + c;
}
}
// 多态应用
public class ShapeTest {
public static void main(String[] args) {
Shape[] shapes = {
new Circle(5),
new Rectangle(4, 6),
new Triangle(3, 4, 5)
};
for (Shape shape : shapes) {
shape.display();
System.out.println();
}
}
}
4. 模板方法模式
public abstract class DataProcessor {
// 模板方法
public final void process() {
readData();
processData();
writeData();
log();
}
// 抽象方法(子类必须实现)
protected abstract void readData();
protected abstract void processData();
protected abstract void writeData();
// 普通方法(可以被重写)
protected void log() {
System.out.println("数据处理完成");
}
}
public class CSVDataProcessor extends DataProcessor {
@Override
protected void readData() {
System.out.println("读取CSV文件");
}
@Override
protected void processData() {
System.out.println("处理CSV数据");
}
@Override
protected void writeData() {
System.out.println("写入CSV文件");
}
@Override
protected void log() {
System.out.println("CSV数据处理完成");
}
}
public class JSONDataProcessor extends DataProcessor {
@Override
protected void readData() {
System.out.println("读取JSON文件");
}
@Override
protected void processData() {
System.out.println("处理JSON数据");
}
@Override
protected void writeData() {
System.out.println("写入JSON文件");
}
}
// 测试
public class TemplateMethodTest {
public static void main(String[] args) {
DataProcessor csvProcessor = new CSVDataProcessor();
csvProcessor.process();
System.out.println();
DataProcessor jsonProcessor = new JSONDataProcessor();
jsonProcessor.process();
}
}
5. 抽象类与接口的区别
抽象类的特点
- 可以有构造方法
- 可以有成员变量
- 可以有普通方法
- 只能继承一个抽象类
- 访问修饰符可以是任意的
接口的特点
- 不能有构造方法
- 只能有常量
- 可以有默认方法和静态方法
- 可以实现多个接口
- 默认是public修饰
// 抽象类
public abstract class AbstractClass {
protected int value;
public AbstractClass(int value) {
this.value = value;
}
public abstract void method1();
public void method2() {
System.out.println("普通方法");
}
}
// 接口
public interface Interface {
int CONSTANT = 10;
void method1();
default void method2() {
System.out.println("默认方法");
}
static void method3() {
System.out.println("静态方法");
}
}
// 类可以继承一个抽象类,实现多个接口
public class MyClass extends AbstractClass implements Interface {
public MyClass(int value) {
super(value);
}
@Override
public void method1() {
System.out.println("实现的方法");
}
}
6. 实际应用示例
员工管理系统
public abstract class Employee {
protected String name;
protected double baseSalary;
public Employee(String name, double baseSalary) {
this.name = name;
this.baseSalary = baseSalary;
}
// 抽象方法
public abstract double calculateSalary();
public abstract String getRole();
// 普通方法
public void display() {
System.out.println("姓名: " + name);
System.out.println("角色: " + getRole());
System.out.println("基本工资: " + baseSalary);
System.out.println("总工资: " + calculateSalary());
System.out.println();
}
public boolean isHigherPaid(Employee other) {
return this.calculateSalary() > other.calculateSalary();
}
}
public class Developer extends Employee {
private double bonus;
public Developer(String name, double baseSalary, double bonus) {
super(name, baseSalary);
this.bonus = bonus;
}
@Override
public double calculateSalary() {
return baseSalary + bonus;
}
@Override
public String getRole() {
return "开发工程师";
}
}
public class Manager extends Employee {
private double teamSize;
private double teamBonus;
public Manager(String name, double baseSalary, double teamSize, double teamBonus) {
super(name, baseSalary);
this.teamSize = teamSize;
this.teamBonus = teamBonus;
}
@Override
public double calculateSalary() {
return baseSalary + (teamBonus * teamSize);
}
@Override
public String getRole() {
return "经理";
}
}
public class EmployeeTest {
public static void main(String[] args) {
Employee dev = new Developer("张三", 10000, 5000);
Employee manager = new Manager("李四", 15000, 5, 2000);
dev.display();
manager.display();
if (dev.isHigherPaid(manager)) {
System.out.println(dev.name + "工资更高");
} else {
System.out.println(manager.name + "工资更高");
}
}
}
7. 最佳实践
- 使用抽象类定义模板:当多个类有共同结构时,使用抽象类
- 抽象方法数量适中:抽象方法太多会导致实现复杂
- 使用模板方法模式:固定算法骨架,让子类实现具体步骤
- 合理使用构造方法:抽象类可以有构造方法供子类调用
- 文档化抽象方法:清楚地文档化抽象方法的契约
总结
抽象类是Java面向对象编程的重要特性。通过抽象类,可以定义类的共同特征、实现代码复用、支持多态。理解抽象类的使用规则和最佳实践,对于设计良好的面向对象程序至关重要。