Java面向对象-抽象类、接口

目录

抽象类

概述

案例

特征

抽象类应用知识:模板方法模式

案例

接口

概述

基本使用:被实现

接口与接口的关系:多继承

JDK 8开始:接口新增方法

第一种:默认方法

第二种:静态方法

第三种:私有方法

注意事项


抽象类

概述

abstract是抽象的意思,可以修饰类、成员方法➡抽象类、抽象方法

比如我们定义了一个父类Animal,里面有个run方法,但是每种动物跑的不一样,我们就可以把它定义成抽象方法,等子类自己去实现

注意事项:

  • 抽象方法只有方法名,不能写方法体
  • 一个类中如果定义了抽象方法,这个类必须声明成抽象类,不然会报错

使用场景:

  • 抽象类可以理解为不完整的设计图,一般作为父类,让子类继承
  • 当父类知道子类一定要完成某些方法,但是每个子类的行为又不同时,父类可以把该方法定义成抽象方法,具体交给子类实现,此时这个类就是抽象类。子类实现时必须要重写

案例

需求:某加油站推出了2种支付卡,一种是预存10000的金卡,后续加油享受8折优惠,另一种是预存5000的银卡,后续加油享受8.5折优惠。

实现2种卡片进入收银系统的逻辑,卡片需要包括主人姓名、余额、支付功能

分析:

  • 创建一张卡片父类:定义属性包括姓名、余额、支付功能(具体交给子类实现)
  • 创建一张金卡:重写支付功能,按照原价8折计算
  • 创建一张银卡:重写支付功能,按照原价8.5折计算

代码参考


public abstract class Card {//父类
    private String userName;
    private double money;

    //定义一个支付功能
    public abstract void pay(double money2);

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public double getMoney() {
        return money;
    }

    public void setMoney(double money) {
        this.money = money;
    }
}


public class goldCard extends Card{//子类金卡
    @Override
    public void pay(double money2) {
        System.out.println("您当前消费:"+money2);
        System.out.println("您的金卡当前余额:"+getMoney());
        //优惠计算:8折
        double rs = money2*0.8;
        System.out.println(getUserName()+"您实际支付:"+rs);
        //更新余额
        setMoney(getMoney()-rs);
    }
}

public class silverCard extends Card{//银卡
    @Override
    public void pay(double money2) {
        System.out.println("您当前消费:"+money2);
        System.out.println("您的银卡当前余额:"+getMoney());
        //优惠计算:8.5折
        double rs = money2*0.85;
        System.out.println(getUserName()+"您实际支付:"+rs);
        //更新余额
        setMoney(getMoney()-rs);
    }
}
public class Test {
    public static void main(String[] args) {
        goldCard c = new goldCard();
        c.setMoney(10000);//金卡
        c.setUserName("gst");
        c.pay(300);//消费300
        System.out.println("余额:"+ c.getMoney());
        System.out.println("--------------------");

        silverCard s = new silverCard();
        s.setMoney(5000);
        s.setUserName("zcy");
        s.pay(100);
        System.out.println("余额:"+s.getMoney());
    }
}

特征

  • 类有的成员,抽象类都具备,比如成员变量、方法构造器
  • 抽象类中不一定有抽象方法,但是有抽象方法的类一定是抽象类
  • 一个类继承了抽象类,必须重写完抽象类中的全部抽象方法,否则这个类也必须定义成抽象类
  • 不能用abstract修饰变量、代码块、构造器
  • 最重要的特征:抽象类不能创建对象

注意:final和abstract是互斥关系

  • abstract定义的抽象类作为模板让子类继承,final定义的类不能被继承
  • 抽象方法定义通用功能让子类重写,final定义的方法子类不能重写

抽象类应用知识:模板方法模式

模板方法模式是一种设计模式

使用场景:当系统中出现同一个功能多处在开发,而该功能的大部分代码是一样的,只有其中部分可能不同的时候,模板方法提高了代码的复用性,使得开发效率更高

实现步骤:

  1. 把功能定义成一个所谓的模板方法,放在抽象类中,模板方法中只定义通用且能确定的代码
  2. 模板方法中不能确定的功能定义成抽象方法让子类去实现

案例

需求:

有两类学生,中学生和小学生,他们都要写一篇作文叫《我的爸爸》,要求他们的作文标题第一段和最后一段内容必须是一样的,正文部分自己发挥

public abstract class Student {//父类

    //声明模板方法
    public final void write(){
        System.out.println("《我的爸爸》");
        System.out.println("描述你的爸爸...");
        //正文部分(每个子类不一样)
        //所以定义成抽象方法交给子类来完成
        System.out.println(writeMain());

        System.out.println("我爱我的爸爸");
    }

    //抽象方法
    public abstract String writeMain();
}
public class primaryS extends Student{//子类
    @Override
    public String writeMain() {
        return "我的爸爸鼻子高高的";
    }//小学生
}
public class middleS extends Student{//子类
    @Override
    public String writeMain() {
        return "我的爸爸太牛啦!";
    }//中学生
public class Test {
    public static void main(String[] args) {
        middleS m = new middleS();
        m.write();//调用父类的方法
        System.out.println("---------------");

        primaryS p = new primaryS();
        p.write();
    }
}

注意:模板方法最好使用final修饰,显得更专业,因为要用这个模板,不能把模板重写呀,不然这个模板不是白弄了嘛,加了final就可以防止子类重写这个模板方法,更安全。

接口

概述

  • 接口用interface关键字来定义

  • 在JDK8之前,接口中只能有常量抽象方法

  • 接口是一种规范,约束别人必须要干某一件事情,而规范默认都是公开的,所以代码层面,常量和抽象方法中的public、static、final、abstract可以省略不写

基本使用:被实现

  • 用法:接口是用来被类实现(implements)的,实现接口的类叫实现类,实现类可以理解为所谓的子类

  • 案例:把运动员定义成接口,将乒乓运动员定义成实现类去实现运动员那个接口,接口是一种规范,运动员这个接口约束着所有乒乓运动员、篮球运动员等都要跑步训练和比赛

  • 接口可以单实现也可以多实现

注意事项:一个类实现接口必须重写完全部接口的全部抽象方法,否则这个类需要定义成抽象类

接口与接口的关系:多继承

基本小结

  • 类与类:单继承
  • 类与接口:多实现
  • 接口与接口:多继承,一个接口可以同时继承多个接口

一个类实现三个接口,如果有十几个接口会很繁琐,可以将几个接口继承到一个接口上,实现接口的多继承

接口多继承的作用:规范合并,整合多个接口为一个接口,便于子类实现

JDK 8开始:接口新增方法

原因:一个系统新开发了升级版本,新版本需要对接口丰富,加入很多个抽象方法,此时改了接口,所有实现类就要全部重写这些新的抽象方法,牵一发而动全身,很繁琐

所以:Java升级技术,允许接口中直接定义带有方法体的方法

第一种:默认方法

类似之前写的实例方法,但是必须用default来修饰(不写的话默认会用public),需要用接口的实现类的对象来调用

第二种:静态方法

必须用static修饰(不写默认用public),接口的静态方法必须用本身的接口名来调用

第三种:私有方法

就是私有的实例方法,必须使用private修饰,从JDK 9才开始有的,只能在本类中被其他默认方法或者私有方法访问

我这边是jdk8所以用不了这个,报错

如果要切换jdk版本这样操作⬇

注:这三种方法在开发时其实很少使用,但是可以帮助我们理解语法

注意事项

  • 接口不能创建对象
  • 一个类实现多个接口,多个接口中有同样的静态方法不冲突

接口的静态方法不能用实现类调用,只能接口自己名字调用,所以上述代码中尽管A和B有相同的静态方法也不冲突

  • 一个类继承了父类,同时又实现了接口,父类中和接口中有同名方法,默认用父类的

Cat这个类继承了Animal父类又实现了Food接口,我们看输出结果默认用了Animal父类的

  • 一个类实现了多个接口,多个接口中存在同名的默认方法,不冲突,这个类重写该方法即可

CC只能自己重写一个go方法,如果一定要用AA或者BB的呢?不好意思,永远用不了!

  • 一个接口继承多个接口,是没有问题的,如果多个接口中存在规范冲突则不能多继承

没问题,而且默认继承一个run就行了,合并起来了

但是这里两个run返回值不一样了,就算冲突报错了

  • 11
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值