欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Java 抽象类 抽象方法 使用说明

程序员文章站 2022-11-21 15:28:18
本文主要介绍什么是抽象类、什么是抽象方法,以及什么时候使用他们,最后还介绍了抽象方法与设计模式,并都附有完整的实例源码和源码详细说明。 ......

知识点

  • 什么是抽象类
    抽象类与普通类主要两点不同:
    1、在类的修饰符后面多了一个abstract关键字
    2、抽象类是不允许通过new来实例化的
    由于抽象类不能通过new来实例化,所以基本上是在继承中当做父类使用。

  • 什么是抽象方法
    抽象方法的定义需要加上abstract关键字,不能有方法体,以封号结尾,比如:
    public abstract void getothersalary();
    抽象方法的具体实现,需要在子类中实现。注意:static、final的方法,不能被申明为抽象方法。

  • 抽象类与抽象方法
    抽象类不一定包含抽象方法,但如果一个类包含了抽象方法,那这个类一定是抽象类,否则编译不通过。

  • 什么时候用抽象方法
    抽象方法通常用于父类中。父类通常都是用于定义一些公共方法、公共属性等,但是实际项目可能会出现某些方法定义在父类中,父类却无法给出具体的实现,此时就是抽象方法出场的时候了。比如下文实例中,职员在公司中的收入都包含基本工资以及绩效奖金,基本工资大家都一样,但是绩效奖金就因岗位而异了,所以绩效奖金在职员类中只是个方法体,没有具体实现。

  • 抽象方法与设计模式
    抽象方法在设计模式中有比较多的体现,特别是用于 模板方法设计模式,详见下文实例

实例

1.抽象方法的使用

需求描述:公司里的职员分为普通程序员和技术总监,所有职员的基本薪水都是10000元每个月,程序员的绩效奖金每个月3000元,技术总监的绩效奖金每个月20000元。

了解了需求后,我们先定义一个职员类employee,如下:

/**
 * 定义职工类,每个职工的薪水都由基本薪资跟绩效奖金组成
 */
public abstract class employee {

    /**
     * 岗位名称
     */
    private string jobname;

    /**
     * 所有职工的每月基本薪资都一样
     * @return
     */
    public int getbasesalary(){
        return 10000;
    }

    /**
     * 所有职工都有绩效奖金,但是普通程序员跟技术总监的不一样,
     * 所以这里无法给出具体实现,需要在子类中实现
     * @return
     */
    public abstract int getothersalary();

    public string getjobname() {
        return jobname;
    }

    public void setjobname(string jobname) {
        this.jobname = jobname;
    }
}

定义程序员类coder,继承职员类,实现getothersalary() 方法,如下:

/**
 * 程序员类,继承employee类
 */
public class coder extends employee{

    /**
     * 由于继承了employee类,所以必须实现employee类中的抽象方法getothersalary()
     * @return
     */
    @override
    public int getothersalary() {
        return 3000;
    }
}

定义技术总监类cto,继承职员类,实现getothersalary() 方法,如下:

/**
 * 技术总监类,继承employee类
 */
public class cto extends employee{

    /**
     * 由于继承了employee类,所以必须实现employee类中的抽象方法getothersalary()
     * @return
     */
    @override
    public int getothersalary() {
        return 20000;
    }
}

最后打印程序员与技术总监每个月的薪水:

public class abstractmain {

    public static void main(string[] args){
        coder coder = new coder();
        coder.setjobname("程序员");
        system.out.println(coder.getjobname() + "每个月薪资为:");
        system.out.println("基本薪资:" + coder.getbasesalary() + "元");
        system.out.println("绩效奖金:" + coder.getothersalary() + "元");

        cto cto = new cto();
        cto.setjobname("技术总监");
        system.out.println(cto.getjobname() + "每个月薪资为:");
        system.out.println("基本薪资:" + cto.getbasesalary() + "元");
        system.out.println("绩效奖金:" + cto.getothersalary() + "元");
    }
}

执行以上程序后,输出:

程序员每个月薪资为:
基本薪资:10000元
绩效奖金:3000元

技术总监每个月薪资为:
基本薪资:10000元
绩效奖金:20000元

2.抽象方法与模板方法设计模式

在完成了以上需求后,此时又提出新需求,按照以下格式打印每个月的工资条,并且打印的顺序必须按以下格式打印出来:

xxx每个月薪资为:
基本薪资:xxx元
绩效奖金:xxx元
该月总工资为:xxx元

按照第一个例子的实现方式无法满足这个需求,第一个例子的打印顺序是由调用者决定的,无法统一控制。此时就是模板方法设计模式登场的时候了。基于第一个例子,改造一下职员类employee,增加打印工资条的方法public final void printsalary()如下:

/**
 * 定义职工类,每个职工的薪水都由基本薪资跟绩效奖金组成
 */
public abstract class employee {

    /**
     * 岗位名称
     */
    private string jobname;

    /**
     * 所有职工的每月基本薪资都一样
     * @return
     */
    public int getbasesalary(){
        return 10000;
    }

    /**
     * 所有职工都有绩效奖金,但是普通程序员跟技术总监的不一样,
     * 所以这里无法给出具体实现,需要在子类中实现
     * @return
     */
    public abstract int getothersalary();

    /**
     * 获取每个月工资总额
     * @return
     */
    public int gettotalsalary(){

        return this.getbasesalary() + this.getothersalary();
    }

    /**
     * 定义执行顺序模板,模板中有些方法(抽象方法)是要在子类中实现
     * 打印工资条,定义为final类,禁止被子类重写
     */
    public final void printsalary(){

        system.out.println(this.jobname + "每个月薪资为:");
        system.out.println("基本薪资:" + this.getbasesalary() + "元");
        system.out.println("绩效奖金:" + this.getothersalary() + "元");
        system.out.println("该月总工资为:" + gettotalsalary() + "元");
    }

    public string getjobname() {
        return jobname;
    }

    public void setjobname(string jobname) {
        this.jobname = jobname;
    }
}

打印每个月工资条:

public class abstractmain {

    public static void main(string[] args){
        coder coder = new coder();
        coder.setjobname("程序员");
        coder.printsalary();

        cto cto = new cto();
        cto.setjobname("技术总监");
        cto.printsalary();
    }
}

以上执行结果为:

程序员每个月薪资为:
基本薪资:10000元
绩效奖金:3000元
该月总工资为:13000元

技术总监每个月薪资为:
基本薪资:10000元
绩效奖金:20000元
该月总工资为:30000元

源码获取

以上示例都可以通过我的github获取完整的代码,