抽象类
1. 认识抽象类
在 Java 中有一个关键字叫:abstract ,它的中文含义是"抽象",可以用它来修饰类、成员方法。
abstract 修饰类,这个类就是抽象类。
abstract 修饰方法,这个方法就是抽象方法。
2. 注意事项
- 抽象类中不一定有抽象方法,但是,有抽象方法的类一定是抽象类
- 类该有的成员(成员变量、成员方法、构造器)抽象类都可以有
- 最大的特点:抽象类不能创建对象!它仅作为一种特殊的父类,让子类继承并实现重写!
abstract class A {private String name;public static String schoolName = "New School";public A() {}public A(String name) {this.name = name;}// A类独有的方法public String getName() {return name;}// A类非独有的方法:被B类继承public void printOut() {System.out.println("通过'普通的模式'的继承实现多态 [from A]");}// "抽象方法"实现了哪些东西?// 1. 父类不用写大括号{},以及对应的代码,因为写了也没意义,交给子类进行重构就好啦!// 2. 强制要求子类,必须对当前的这个抽象方法进行重构,否则子类也会被同化成抽象类!// 3. 综上所述,抽象类与抽象方法最终只是为了让子类强制执行重构,以实现更好的"多态"// 所以,不使用抽象类来打造"多态"也是可以的,但是显得不那么专业。public abstract void run();// 如果使用普通的模式让子类进行重构,从而实现"多态",上面的代码则应该改成——如下所示:
// public void run(){
//
// }
}class B extends A {// 调用A类的构造器public B(String name) {super(name);}// B类独有的方法public void helloWorld() {System.out.println("Hello World");}// 继承A类的方法,普通的模式进行继承,实现多态@Overridepublic void printOut() {System.out.println("通过'普通的模式'的继承实现多态 [from B]");}// 当B类继承了A类,// 要么选择: 将A类中的抽象方法run()进行重构,// 要么选择: B类也变成抽象类,// 要么选择: 程序报错!public void run() {System.out.println("B类: 正在跑步...");}
}public class HelloWorld {public static void main(String[] args) {
// A obj = new A(); // 报错,A类是抽象类,无法创建对象A obj = new B("Jack"); // 正常System.out.println(obj.schoolName); // (A类的属性[或者说成员变量])System.out.println(obj.getName()); // (A类的独有方法)obj.printOut(); // (B类的方法:它是重写了A类的)
// obj.helloWorld(); // 报错 (B类的独有方法)// 执行结果:// New School// Jack// 通过'普通的模式'的继承实现多态 [from B]}
}
3. 抽象类的意义
抽象类的应用场景和好处是,父类知道每个子类都要做某个行为,但是在每个子类中要做的情况不一样,父类就定义成抽象方法,交给子类去强制重写。我们抽象出这样的抽象类,就是为了更好的支持多态。
4. 抽象类的应用
4.1 模板方法设计模式
- 抽象类的常见应用场景:模板方法设计模式
- 模板方法设计模式:解决了方法中存在重复代码的问题
4.2 写法
- 定义一个抽象类
- 在里面定义两个方法
- 一个是模板方法:把需要重复使用的代码放进去
- 一个是抽象方法:具体的功能实现交给子类完成
abstract class People {// 没有被继承的成员方法// 像这种不需要被继承的方法,强烈建议加上 final 关键字,以防止不小心被重写了!public final void speak() {System.out.println("这个人正在台上演讲...");System.out.println(speakMain());System.out.println("这个人演讲结束啦");}// 抽象方法public abstract String speakMain();
}class Teacher extends People {// 以Teacher风格,重写抽象方法public String speakMain() {return "这个人是老师,演讲的内容很有深度!";}
}class Student extends People {// 以Student风格,重写抽象方法public String speakMain() {return "这个人是学生,在台上演讲有点紧张。";}
}public class Test {public static void main(String[] args) {People p1 = new Teacher();People p2 = new Student();p1.speak();System.out.println("-------------------------");p2.speak();}
}// 运行结果://这个人正在台上演讲...
//这个人是老师,演讲的内容很有深度!
//这个人演讲结束啦
//-------------------------
//这个人正在台上演讲...
//这个人是学生,在台上演讲有点紧张。
//这个人演讲结束啦