随着继承层次中一个个新子类的定义,类变得越来越具体,而父类则更一般,更通用。类的设计应该保证父类和子类能够共享特征。有时将一个父类设计得非常抽象,以至于它没有具体的实例,这样的类叫做抽象类

1、抽象类的使用

1、abstract:抽象的

2、abstract可以用来修饰的结构:类、方法

3、abstract 修饰类:抽象类

  • 此类不能被实例化
  • 抽象类中一定有构造器,便于子类实例化时调用(涉及:子类对象实例化全过程)
  • 开发中,都会提供抽象类的子类,让子类对象实例化,实现相关的操作

    4、abstract 修饰方法:抽象方法

  • 抽象方法,只有方法的声明,没有方法体。

  • 包含抽象方法的类,一定是一个抽象类。反之,抽象类中可以没有抽象方法。
  • 若子类重写了父类的所有的抽象方法,此子类可以实例化

    5、abstract 使用上的注意点

  • abstract不能修饰变量,代码块,构造器;

  • abstract 不能用来修饰私有方法、静态方法、final的方法、final的类

    2、抽象类应用

    抽象类是用来模型化那些父类无法确定全部实现,而是由其子类提供具体实现的对象的类。
    image.png
    问题:卡车(Truck)和驳船(RiverBarge)的燃料效率和行驶距离的计算方法完全不同。Vehicle 类不能提供计算方法,但子类可以。 ```java /* Java 允许类设计者指定:超类声明一个方法但不提供实现,该方法的实现由子类提 供。这样的方法称为抽象方法。有一个或更多抽象方法的类称为抽象类。
    • Vehicle 是一个抽象类,有两个抽象方法。
    • 注意:抽象类不能实例化 new Vihicle()是非法的 */ public abstract class Vehicle{ public abstract double calcFuelEfficiency();//计算燃料效率的抽象方法 public abstract double calcTripDistance();//计算行驶距离的抽象方法 } public class Truck extends Vehicle{ public double calcFuelEfficiency(){
      1. //写出计算卡车的燃料效率的具体方法
      } public double calcTripDistance(){
      1. //写出计算卡车行驶距离的具体方法
      } } public class RiverBarge extends Vehicle{ public double calcFuelEfficiency() {
      1. //写出计算驳船的燃料效率的具体方法
      } public double calcTripDistance( ) {
      1. //写出计算驳船行驶距离的具体方法
      } }
  1. <a name="vNhfM"></a>
  2. # 3、创建抽象类的匿名子类对象
  3. ```java
  4. /*
  5. * 抽象类的匿名子类
  6. *
  7. */
  8. public class PersonTest {
  9. public static void main(String[] args) {
  10. method(new Student()); //匿名对象
  11. Worker worker = new Worker();
  12. method1(worker); //非匿名的类非匿名的对象
  13. method1(new Worker()); //非匿名的类匿名的对象
  14. System.out.println("*********************");
  15. //创建了一个匿名子类的对象:p
  16. Person p = new Person(){
  17. @Override
  18. public void eat() {
  19. System.out.println("吃东西");
  20. }
  21. @Override
  22. public void breath() {
  23. System.out.println("呼吸空气");
  24. }
  25. };
  26. method1(p);
  27. System.out.println("**********************");
  28. //创建匿名子类的匿名对象
  29. method1(new Person(){
  30. @Override
  31. public void eat() {
  32. System.out.println("吃零食");
  33. }
  34. @Override
  35. public void breath() {
  36. System.out.println("云南的空气");
  37. }
  38. });
  39. }
  40. public static void method1(Person p){
  41. p.eat();
  42. p.walk();
  43. }
  44. public static void method(Student s){
  45. }
  46. }
  47. class Worker extends Person{
  48. @Override
  49. public void eat() {
  50. }
  51. @Override
  52. public void breath() {
  53. }
  54. }

4、多态的应用:模板方法设计模式(TemplateMethod)

抽象类体现的就是一种模板模式的设计,抽象类作为多个子类的通用模板,子类在抽象类的基础上进行扩展、改造,但子类总体上会保留抽象类的行为方式。

解决的问题:
当功能内部一部分实现是确定的,一部分实现是不确定的。这时可以把不确定的部分暴露出去,让子类去实现。
换句话说,在软件开发中实现一个算法时,整体步骤很固定、通用,这些步骤已经在父类中写好了。但是某些部分易变,易变部分可以抽象出来,供不同子类实现。这就是一种模板模式

  1. /*
  2. * 抽象类的应用:模板方法的设计模式
  3. */
  4. public class TemplateTest {
  5. public static void main(String[] args) {
  6. SubTemlate t = new SubTemlate();
  7. t.sendTime();
  8. }
  9. }
  10. abstract class Template{
  11. //计算某段代码执行所需花费的时间
  12. public void sendTime(){
  13. long start = System.currentTimeMillis();
  14. code(); //不确定部分,易变的部分
  15. long end = System.currentTimeMillis();
  16. System.out.println("花费的时间为:" + (end - start));
  17. }
  18. public abstract void code();
  19. }
  20. class SubTemlate extends Template{
  21. @Override
  22. public void code() {
  23. for(int i = 2;i <= 1000;i++){
  24. boolean isFlag = true;
  25. for(int j = 2;j <= Math.sqrt(i);j++){
  26. if(i % j == 0){
  27. isFlag = false;
  28. break;
  29. }
  30. }
  31. if(isFlag){
  32. System.out.println(i);
  33. }
  34. }
  35. }
  36. }
  1. //抽象类的应用:模板方法的设计模式
  2. public class TemplateMethodTest {
  3. public static void main(String[] args) {
  4. BankTemplateMethod btm = new DrawMoney();
  5. btm.process();
  6. BankTemplateMethod btm2 = new ManageMoney();
  7. btm2.process();
  8. }
  9. }
  10. abstract class BankTemplateMethod {
  11. // 具体方法
  12. public void takeNumber() {
  13. System.out.println("取号排队");
  14. }
  15. public abstract void transact(); // 办理具体的业务 //钩子方法
  16. public void evaluate() {
  17. System.out.println("反馈评分");
  18. }
  19. // 模板方法,把基本操作组合到一起,子类一般不能重写
  20. public final void process() {
  21. this.takeNumber();
  22. this.transact();// 像个钩子,具体执行时,挂哪个子类,就执行哪个子类的实现代码
  23. this.evaluate();
  24. }
  25. }
  26. class DrawMoney extends BankTemplateMethod {
  27. public void transact() {
  28. System.out.println("我要取款!!!");
  29. }
  30. }
  31. class ManageMoney extends BankTemplateMethod {
  32. public void transact() {
  33. System.out.println("我要理财!我这里有 2000 万美元!!");
  34. }
  35. }

模板方法设计模式是编程中经常用得到的模式。各个框架、类库中都有他的影子,比如常见的有:

  • 数据库访问的封装
  • Junit 单元测试
  • JavaWeb 的 Servlet 中关于 doGet/doPost 方法调用
  • Hibernate 中模板程序
  • Spring 中 JDBCTemlate、HibernateTemplate 等