抽象类与抽象方法

我们声明一些几何图形类:圆、矩形、三角形类等,发现这些类都有共同特征:求面积、求周长。那么这些共同特征应该抽取到一个共同父类:几何图形类中。但是这些方法在父类中又无法给出具体的实现,而是应该交给子类各自具体实现。那么父类在声明这些方法时,就只有方法签名,没有方法体,我们把没有方法体的方法称为抽象方法。Java语法规定,包含抽象方法的类必须是抽象类

1. 语法格式

  • 抽象类:被abstract修饰的类。

  • 抽象方法:被abstract修饰没有方法体的方法。

抽象类的语法格式

[权限修饰符] abstract class 类名{  
      
}  
[权限修饰符] abstract class 类名 extends 父类{  
      
}

抽象方法的语法格式

[其他修饰符] abstract 返回值类型 方法名([形参列表]);

注意:抽象方法没有方法体

代码举例:

public abstract class Animal {  
    public abstract void eat();  
}

public class Cat extends Animal {  
    public void eat (){  
        System.out.println("小猫吃鱼和猫粮");   
    }  
}

public class CatTest {  
     public static void main(String[] args) {  
        // 创建子类对象  
        Cat c = new Cat();   
         
        // 调用eat方法  
        c.eat();  
    }  
}

此时的方法重写,是子类对父类抽象方法的完成实现,我们将这种方法重写的操作,也叫做实现方法

2. 使用说明

  1. 抽象类不能创建对象,如果创建,编译无法通过而报错。只能创建其非抽象子类的对象。

    理解:假设创建了抽象类的对象,调用抽象的方法,而抽象方法没有具体的方法体,没有意义。

    抽象类是用来被继承的,抽象类的子类必须重写父类的抽象方法,并提供方法体。若没有重写全部的抽象方法,仍为抽象类。

  2. 抽象类中,也有构造方法,是供子类创建对象时,初始化父类成员变量使用的。

    理解:子类的构造方法中,有默认的super()或手动的super(实参列表),需要访问父类构造方法。

  3. 抽象类中,不一定包含抽象方法,但是有抽象方法的类必定是抽象类。

    理解:未包含抽象方法的抽象类,目的就是不想让调用者创建该类对象,通常用于某些特殊的类结构设计。

  4. 抽象类的子类,必须重写抽象父类中所有的抽象方法,否则,编译无法通过而报错。除非该子类也是抽象类。

    理解:假设不重写所有抽象方法,则类中可能包含抽象方法。那么创建对象后,调用抽象的方法,没有意义。

3. 注意事项

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

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

4. 应用举例1

image-20220325232847872

在航运公司系统中,Vehicle类需要定义两个方法分别计算运输工具的燃料效率行驶距离

问题:卡车(Truck)和驳船(RiverBarge)的燃料效率和行驶距离的计算方法完全不同。Vehicle类不能提供计算方法,但子类可以。

解决方案:Java允许类设计者指定:超类声明一个方法但不提供实现,该方法的实现由子类提供。这样的方法称为抽象方法。有一个或更多抽象方法的类称为抽象类。

//Vehicle是一个抽象类,有两个抽象方法。  
public abstract class Vehicle{  
    public abstract double calcFuelEfficiency();    //计算燃料效率的抽象方法  
    public abstract double calcTripDistance();  //计算行驶距离的抽象方法  
}  
public class Truck extends Vehicle{  
    public double calcFuelEfficiency( )   { //写出计算卡车的燃料效率的具体方法   }  
    public double calcTripDistance( )    {  //写出计算卡车行驶距离的具体方法   }  
}  
public class RiverBarge extends Vehicle{  
     public double calcFuelEfficiency( ) { //写出计算驳船的燃料效率的具体方法  }  
     public double calcTripDistance( )  {  //写出计算驳船行驶距离的具体方法}  
}  

5. 应用举例2:模板方法设计模式(TemplateMethod)

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

解决的问题

  • 当功能内部一部分实现是确定的,另一部分实现是不确定的。这时可以把不确定的部分暴露出去,让子类去实现。

  • 换句话说,在软件开发中实现一个算法时,整体步骤很固定、通用,这些步骤已经在父类中写好了。但是某些部分易变,易变部分可以抽象出来,供不同子类实现。这就是一种模板模式。

**类比举例:**英语六级模板

image-20220503145003315

abstract class Template {  
    public final void getTime() {  
        long start = System.currentTimeMillis();  
        code();  
        long end = System.currentTimeMillis();  
        System.out.println("执行时间是:" + (end - start));  
    }  
​  
    public abstract void code();  
}  
​  
class SubTemplate extends Template {  
    public void code() {  
        for (int i = 0; i < 10000; i++) {  
            System.out.println(i);  
        }  
    }  
}  

举例2:

package com.atguigu.java;  
//抽象类的应用:模板方法的设计模式  
public class TemplateMethodTest {  
​  
    public static void main(String[] args) {  
        BankTemplateMethod btm = new DrawMoney();  
        btm.process();  
​  
        BankTemplateMethod btm2 = new ManageMoney();  
        btm2.process();  
    }  
}  
abstract class BankTemplateMethod {  
    // 具体方法  
    public void takeNumber() {  
        System.out.println("取号排队");  
    }  
​  
    public abstract void transact(); // 办理具体的业务 //钩子方法  
​  
    public void evaluate() {  
        System.out.println("反馈评分");  
    }  
​  
    // 模板方法,把基本操作组合到一起,子类一般不能重写  
    public final void process() {  
        this.takeNumber();  
​  
        this.transact();// 像个钩子,具体执行时,挂哪个子类,就执行哪个子类的实现代码  
​  
        this.evaluate();  
    }  
}  
​  
class DrawMoney extends BankTemplateMethod {  
    public void transact() {  
        System.out.println("我要取款!!!");  
    }  
}  
​  
class ManageMoney extends BankTemplateMethod {  
    public void transact() {  
        System.out.println("我要理财!我这里有2000万美元!!");  
    }  
}  

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

  • 数据库访问的封装

  • Junit单元测试

  • JavaWeb的Servlet中关于doGet/doPost方法调用

  • Hibernate中模板程序

  • Spring中JDBCTemlate、HibernateTemplate等

Java基础

Object 类的使用

2025-8-8 20:25:02

Java基础

接口(interface)

2025-8-9 10:21:57

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
今日签到
有新私信 私信列表
搜索