抽象类的定义
在 Java 里,抽象类是使用 abstract 关键字修饰的类。它无法被实例化,主要用于作为其他类的父类,为子类提供一个通用的模板,规定子类必须实现的方法.
代码示例分析
package nuuyoah.abstract1;
public abstract class A {
private int a;
public int b;
protected int c;
public static int d;
public A() {
}
public A(int a, int b, int c, int d) {
this.a = a;
this.b = b;
this.c = c;
this.d = d;
}
public void method() {
System.out.println("method");
}
public abstract void eat();
}
- 抽象类的定义:
public abstract class A
表明A
是一个抽象类。 - 成员变量:包含了不同访问修饰符的成员变量,如
private、public、protected
和static
修饰的变量。 - 构造方法:有一个无参构造方法和一个带参构造方法,用于初始化成员变量。
- 非抽象方法:
method()
是一个普通的非抽象方法,有具体的方法实现。 - 抽象方法:
public abstract void eat();
是抽象方法,使用abstract
关键字修饰,没有方法体,需要子类去实现。
package nuuyoah.abstract1;
public class B extends A {
@Override
public void eat() {
System.out.println("B类实现了eat方法");
}
}
- 子类继承抽象类:
class B extends A
表明B
类继承自抽象类A
。 - 实现抽象方法:
B
类必须实现 A 类中的抽象方法eat()
,否则B
类也需要被定义为抽象类。
package nuuyoah.abstract1;
public class Test {
public static void main(String[] args) {
// 抽象类不能创建对象
// A a = new A(); // 编译错误
B b = new B();
b.eat();
b.method();
}
}
- 抽象类不能实例化:
A a = new A();
会导致编译错误,因为抽象类不能被实例化。 - 子类实例化:可以创建
B
类的对象,并调用其实现的eat()
方法和从A
类继承的method()
方法。
抽象类的注意事项、特点
- 抽象类中不一定要有抽象方法,有抽象方法的类必须是抽象类。
- 类有的成员:成员变量、方法、构造器,抽象类都可以有。
- 抽象类最主要的特点:抽象类不能创建对象,仅作为一种特殊的父类,让子类继承并实现。
- 一个类继承抽象类,必须重写完抽象类的全部抽象方法,否则这个类也必须定义成抽象类。
使用抽象类的好处
实现多态
多态允许不同的对象对同一消息做出不同的响应,提高了代码的灵活性和可扩展性。借助抽象类,我们可以定义统一的接口,让子类根据自身需求去实现,从而实现多态。
public class Test {
public static void main(String[] args) {
Animal animal = new Cat();
animal.shout();//🐱:喵喵喵
animal = new Dog();
animal.shout();//🐕:汪汪汪
}
}
这里 Animal
类型的引用变量 animal
可以先后指向 Cat
和 Dog
对象。当调用 shout()
方法时,会根据实际指向的对象类型来调用相应的实现,这就是多态的体现。若不使用抽象类,就难以实现这种统一接口下不同行为的调用。
强制规范子类行为
抽象类里的抽象方法没有具体实现,子类必须对其进行重写。这样能确保子类具备特定的行为,保证代码的规范性和一致性。
public abstract class Animal {
public abstract void shout();
}
Animal
类定义了抽象方法 shout()
,任何继承自 Animal
的子类都必须实现这个方法。像必须实现 Cat
类和 Dog
类:
public class Cat extends Animal{
@Override
public void shout() {
System.out.println("🐱:喵喵喵");
}
}
public class Dog extends Animal{
@Override
public void shout() {
System.out.println("🐶:汪汪汪");
}
}
它们都实现了 shout()
方法,保证了所有 Animal
的子类都能发出叫声。
提高代码的可维护性和可扩展性
抽象类能够作为一个通用的基类,为子类提供公共的属性和方法。当需要修改或扩展功能时,只需在抽象类中进行操作,所有子类都会受到影响。
假如要给 Animal
类添加一个新的抽象方法,比如 sleep()
,只需要在 Animal
类中添加:
public abstract class Animal {
public abstract void shout();
public abstract void sleep();
}
然后在 Cat
和 Dog
等子类中实现 sleep()
方法即可,这样的修改不会影响到使用 Animal
类引用的代码,提高了代码的可维护性和可扩展性。
隐藏实现细节
抽象类可以隐藏具体的实现细节,只向外部暴露必要的接口。外部代码只需要通过抽象类的引用调用方法,而不需要关心具体的实现。
在 Test
类中,调用 animal.shout()
时,不需要知道具体是 Cat
还是 Dog
实现了shout()
方法,只需要知道 Animal
类有shout()
方法就行,这隐藏了具体的实现细节,降低了代码的耦合度。
抽象类模板方法设计模式
提供一个方法作为完成某类功能的模板模板方法封装了每个实现步骤,但允许子类提供特定步骤的实现。
模板方法设计模式可以:提高代码的复用、并简化子类设计。
抽象类模板方法设计模式是一种行为设计模式,它定义了一个算法的骨架,将一些步骤的实现延迟到子类中。在这个案例中,以写作文《我的爸爸》为例,展示了抽象类模板方法设计模式的应用。下面详细解释其步骤和流程逻辑。
- 定义抽象类
创建一个抽象类,其中包含模板方法和抽象方法。模板方法定义了算法的骨架,而抽象方法则由子类来具体实现。
public abstract class People {
// 模板方法,定义了写作文的整体流程
public final void write() {
System.out.println("\t\t\t《我的爸爸》");
System.out.println("\t我爸爸是一个好人,我特别喜欢他,他对我很好,我来介绍一下:");
// 调用抽象方法,由子类实现具体内容
writeBody();
System.out.println("\t我爸爸真好,你有这样的爸爸吗?");
}
// 抽象方法,由子类实现具体的作文正文内容
public abstract void writeBody();
}
注:建议使用 final 关键字修饰模板方法
这里 People
是抽象类,write()
是模板方法,writeBody()
是抽象方法。
- 创建具体子类
创建具体的子类继承抽象类,并实现抽象方法。
public class Student extends People {
@Override
public void writeBody() {
System.out.println("\t我的爸爸是个董事长,我买东西从不花钱,我喜欢他,我爸爸真好!");
}
}
public class Teacher extends People {
@Override
public void writeBody() {
System.out.println("\t我的爸爸是个老师,我教学生,我喜欢他,我爸爸真好!");
}
}
Student 和 Teacher 类继承自 People 类,并实现了 writeBody() 方法,分别给出了学生和老师写作文正文的具体内容。
- 使用模板方法
在客户端代码中,创建具体子类的对象,并调用模板方法。
public class Test {
public static void main(String[] args) {
// 创建学生对象,调用模板方法
Student student = new Student();
student.write();
// 创建老师对象,调用模板方法
Teacher teacher = new Teacher();
teacher.write();
}
}
通过创建 Student
和 Teacher
对象,并调用它们的write()
方法,触发了模板方法的执行。
流程逻辑
- 客户端调用模板方法:在
Test
类的main
方法中,创建Student
和Teacher
对象,并调用它们的write()
方法。 - 模板方法执行:
write()
方法作为模板方法,定义了写作文的整体流程。它先输出作文的标题和第一段固定内容,然后调用writeBody()
方法。 - 子类实现的抽象方法执行:由于
writeBody()
是抽象方法,具体的实现由子类完成。在 Stu``dent 类中,输出学生视角的作文正文;在Teacher
类中,输出老师视角的作文正文。 - 模板方法继续执行:在
writeBody()
方法执行完毕后,模板方法继续输出作文的最后一段固定内容。
通过这种方式,抽象类模板方法设计模式将算法的骨架和具体实现分离,提高了代码的复用性和可维护性。不同的子类可以根据自己的需求实现抽象方法,而模板方法定义的整体流程保持不变。