【JAVA学习笔记】40 - 抽象类、模版设计模式(抽象类的使用)

项目代码

https://github.com/yinhai1114/Java_Learning_Code/tree/main/IDEA_Chapter10/src/com/yinhai/abstract_

一、抽象类的引入

        很多时候在创建类的时候有一个父类,比如animal类,他的子类会有各种方法,为了复用需要进行方法的重写,比如子类Cat会eat(),所以不得已只能在animal类内也需要写eat()方法,但没有意义。

        所以当父类的某些方法,需要声明,但是又不确定如何实现时,可以将其声明为抽象方法,那么这个类就是抽象类。

abstract class Animal{
    // public void eat(){System.out.println("eat但不知道谁在吃");}//所以需要抽象方法
        //这里实现了eat(),但其实没有什么意义
        //即 父类方法不确定性的问题
        //===>考虑该方法设计为抽象(abstract)方法
        //==>所谓抽象方法就是没有实现的方法
        //===>所谓没有实现就是指,没有方法体
    abstract public void eat();
        //注意 当一个类中存在抽家方法时,需要将该类声明为abstract类

        //所以一般是子类来实现这个抽象方法的重写
}
class Cat extends Animal{
    public void eat(){
        System.out.println("小猫在吃....");
    }
}

二、抽象类的基本介绍

1)用abstract关键字来修饰个类时,这个类就叫抽象类访问修饰符abstract类名{

2)用abstract关键字来修饰一个方法时,这个方法就是抽象方法访问修饰符abstract返回类型方法名(参数列表)//没有方法体

【JAVA学习笔记】40 - 抽象类、模版设计模式(抽象类的使用)_第1张图片

3)抽象类的价值更多作用是在于设计,是设计者设计好后,让子类继承并实现抽象类()

4)抽象类,是考官比较爱问的知识点在框架和设计模式使用较多

三、抽象类的注意事项和细节讨论

1)抽象类不能被实例化

报错'A' is abstract; cannot be instantiated

【JAVA学习笔记】40 - 抽象类、模版设计模式(抽象类的使用)_第2张图片

2)抽象类不定要包含abstract方法。 也就是说抽象类可以没有abstract方法

        同上 上图的抽象类A类并没有抽象方法

3)一旦类包含了abstract方法,则这个类必须声明为abstract

【JAVA学习笔记】40 - 抽象类、模版设计模式(抽象类的使用)_第3张图片

4) abstract只能修饰类和方法,不能修饰属性和其它的。

【JAVA学习笔记】40 - 抽象类、模版设计模式(抽象类的使用)_第4张图片

5)抽象类可以有任意成员(抽象类本质还是类),比如:非抽象方法、构造器、静态属性等等

注意不能实例对象。

public class AbstractDetail02 {
    public static void main(String[] args) {
        D.nihao();
    }
}
abstract class D{
    public int n1 = 10;
    public static String name = "yinhai";
    public D(){

    }
    {

    }
    static {

    }
    public abstract void hello();
    public void ok(){

    }
    public static void nihao (){

    }
}

6)抽象方法不能有主体,即不能实现如图所示abstract void aaa(){};

7)如果个类继承 了抽象类, 则它必须实现抽象类的所有抽象方法,除非它自己也声明为abstract类。
【JAVA学习笔记】40 - 抽象类、模版设计模式(抽象类的使用)_第5张图片

abstract class E{
    public abstract void hi();
}
abstract class F extends E{
    
}
class G extends E{
    @Override
    public void hi() {//这里G类子类实现了父类E的抽象方法,就是有方法体
        
    }
}

8)抽象方法不能使用private,final和static来修饰,因为这些关键字都是和重写相违背的。

        【JAVA学习笔记】40 - 抽象类、模版设计模式(抽象类的使用)_第6张图片

 四、抽象类的课堂练习

1)题1.思考: abstract final class A{}能编译通过吗,why?

        // 不能 因为抽象的本意是继承重写

        //final修饰就已经是最终类了

2)题2,思考: abstract public static void test2(); 能编译通过吗,why?

        //不能 静态的方法是不能重写的

3)题3,思考: abstract private void test30;能编译通过吗,why?

        //不能 除了public以外都不行

4)编写一个Employee类,声明为抽象类,包含如下三个属性: name, id, salary.提供必要的构造器和抽象方法: work0. 对于Manager类来说,他既是员工,还具有奖金(bonus)的属性。请使用继承的思想,设计CommonEmployee类和Manager类.要求类中提供必要的方法进行属性访问,实现work().提示"经理/普通员工名字工作中....


    public double getSalary() {
        return salary;
    }

    public void setSalary(double salary) {
        this.salary = salary;
    }
}
class Maanager extends Employee{
    private double bonus;

    public Maanager(String name, String id, double salary, double bonus) {
        super(name, id, salary);
        this.bonus = bonus;
    }

    public void work(){
        System.out.println("经理 " + getName() + "正在工作中");
    }
}
class CommonEmployee extends Employee{
    public void work(){
        System.out.println("普通员工 " + getName() + "正在工作中");
    }

    public CommonEmployee(String name, String id, double salary) {
        super(name, id, salary);
    }
}

 【JAVA学习笔记】40 - 抽象类、模版设计模式(抽象类的使用)_第7张图片

五、模版设计模式

需求

1.有多个类,完成不同的任务job

2.要求统计各自得到各自完成任务的时间

3.编程实现

引出模版设计模式

public class TestTemplate {
    public static void main(String[] args) {
        AA aa = new AA();
        aa.job();
        BB bb = new BB();
        bb.job();
    }
}

class AA {

    public void job() {

        //得到开始的时间
        long start = System.currentTimeMillis();
        long num = 0;
        for (long i = 0; i < 1000000; i++) {
            num += i;
        }
        //得到结束的时间
        long end = System.currentTimeMillis();
        System.out.println("执行时间" + (end - start) + "ms");
    }
    public void job2(){
        //得到开始的时间
        long start = System.currentTimeMillis();
        long num = 0;
        for (long i = 0; i < 3000000; i++) {
            num += i;
        }
        //得到结束的时间
        long end = System.currentTimeMillis();
        System.out.println("执行时间" + (end - start) + "ms");
    }
}

class BB {
    public void job() {

        //得到开始的时间
        long start = System.currentTimeMillis();
        long num = 0;
        for (long i = 0; i < 2000000; i++) {
            num += i;
        }
        //得到结束的时间
        long end = System.currentTimeMillis();
        System.out.println("执行时间" + (end - start) + "ms");
    }
}

【JAVA学习笔记】40 - 抽象类、模版设计模式(抽象类的使用)_第8张图片

        如果在每个单类里面写job和计算时间的代码块,复用性会很差,所以就引出模版设计,设计一个父类,里面塞进去共有的计算时间的方法,然后塞入抽象job方法,因为每一个对象在运行的时候会从本类开始查找,所以构成了重写抽象job方法,所以这种设计理念就相当于把父类作为一个模版,其他继承。

所以改进该代码

public class TestTemplate {
    public static void main(String[] args) {
        AA aa = new AA();
        BB bb = new BB();
        aa.calWorkTime();
        bb.calWorkTime();
    }
}
abstract class Template{
    public abstract void job();
    public void calWorkTime(){
        long start = System.currentTimeMillis();
        job();//动态绑定机制,调用的是对象所在类内的方法,没有再往上查找
        long end = System.currentTimeMillis();
        System.out.println("执行时间" + (end - start) + "ms");
    }
}
class AA extends Template{

    public void job() {
        long num = 0;
        for (long i = 0; i < 1000000; i++) {
            num += i;
        }
    }
}
class BB extends Template{
    public void job() {
        long num = 0;
        for (long i = 0; i < 2000000; i++) {
            num += i;
        }
    }
}

        【JAVA学习笔记】40 - 抽象类、模版设计模式(抽象类的使用)_第9张图片

你可能感兴趣的:(java,学习,笔记)