Skip to content

day02 【接口、多态】

今日内容介绍

java
接口
多态
综合练习

第一章 接口

1.1 接口的概念【重点】

java
1.概念:
	对外暴露的规则/规范/标准,只要符合该规则/规范/标准的东西都可以使用

2.接口,是Java语言中一种引用类型,也是.java结尾的,编译后也有对应的class文件,是方法的汇总

3.作用: 实现对类的功能的扩展,解决java中类的单继承的局限性。

1.3 接口的定义格式【重点】

在最初设计理念里面,接口里面只能有抽象的方法,它就是一个抽象方法的集合。

所以它没有构造方法,不能进行实例化。

因为抽象方法,所以只有方法的定义格式(声明),没有实现。

如果想要用,我们需要写一个类去实现接口。

java
定义接口的格式
public interface 接口名称{

    //jdk7 的时候 抽象方法
}
怎么实现呢?
public class 实现类名 implements 接口名{
    //必须要重写抽象方法

}

public abstract class 实现类名 implements 接口名{


}

1.4 接口中抽象方法的定义格式和使用【重点】

接口的定义

java
package com.itheima.interface01;
/*
  接口中
    最初设计的时候要求
      里面的方法是抽象的方法
       格式:
       public abstract 返回值类型 方法名();

       特点
         只有抽象方法,没有任何实现。
         相当于定义了规则
         由具体的实现类实现这些功能。
      设计的好处
         我这里定义了规范,实现类哪里完成具体的实现。
         解耦!!把方法的声明与方法的实现进行拆分。
         符合我们社会的规则,
           好比电脑上的usb接口,定义很多规则,传输协议。
           只要我们的 usb设备符合该规则就可以进行连接。
 */
public interface MyInterface {


    public abstract void method();
    public abstract void method2();
}

接口的实现

java
package com.itheima.interface01;
//使用一个具体的类 实现了接口   其实是实现接口的抽象方法
public class MyClassImpl implements MyInterface {
    @Override
    public void method() {
        System.out.println("我重写后的method");
    }

    @Override
    public void method2() {
        System.out.println("我重写后的method2");
    }
}

测试:

java
package com.itheima.interface01;

public class Demo {

    public static void main(String[] args) {
        MyClassImpl myClass = new MyClassImpl();

        myClass.method();//调用的是重写后的方法
        myClass.method2();//调用的是重写后的方法
    }
}

1640569510258

1.5 完成一个 USB 接口案例

usb 接口

java
package com.itheima.interface02;

public interface USB {
    //usb设备具备连接电脑的功能
    public abstract void link();
    //usb设备具备  传输的功能
    public abstract void transfer();
}

键盘类

java
package com.itheima.interface02;
//想要连接电脑 必须 进行实现usb接口
public class KeyBoard implements USB{

    public void daZi(){
        System.out.println("键盘具备打字的功能");
    }

    @Override
    public void link() {
        System.out.println("键盘连接电脑了");
    }

    @Override
    public void transfer() {
        System.out.println("键盘传输 键的信号 ");
    }
}

测试类

java
package com.itheima.interface02;

public class Demo {

    public static void main(String[] args) {
        KeyBoard keyBoard = new KeyBoard();

        //连接电脑
        keyBoard.link();
        //打字
        keyBoard.daZi();
        // 传输信号
        keyBoard.transfer();
    }
}

1640569914852

1.6 接口里面有什么(jdk8 之前的 jdk7)重点

1640570489302

有常量

java
public interface 接口{
    //成员变量--常量  一旦定义不能更改
    //public static final int num;//错误的,因为你是常量,所以定义的时候必须完成赋值。
    public static final int num=1;//正确的
    int num2 = 2;//正确的 因为 你不写修饰符 默认修饰符  public static final 让变量变常量。
}

例子

java
package com.itheima.interface03;

public interface MyInterface {
    public static final int num = 1;//这是完整的定义格式
    int num2 = 2;//这是省略格式 说明有默认的修饰符会加上
}
java
package com.itheima.interface03;

public class Demo {

    public static void main(String[] args) {
        System.out.println(MyInterface.num);
        System.out.println(MyInterface.num2);

//        MyInterface.num=11;报错因为常量只能赋值一次
    }
}

还有抽象方法

java
package com.itheima.interface03;

public interface MyInterface {
    public static final int num = 1;//这是完整的定义格式
    int num2 = 2;//这是省略格式 说明有默认的修饰符会加上
    //抽象方法  完整写法
    public abstract void show();
    // 你不写 修饰符 有默认的修饰符 public abstract
    void show2();
}

1.7 JDK1.8(JDK8)接口的新特性【了解】

为了提升接口的扩展性,降低维护性,所以允许了定义带有方法体的方法

1.7.1 允许 默认方法的存在

java
格式 public default 返回值类型 方法名(...){
        方法体
    }

作用:解决接口升级问题

特点:

 *  子类可以不用重写默认方法,一样可以使用

演示代码

接口

java
package com.itheima.interface04;

public interface MyInterface {

    //jdk8之后允许  接口中定义带有方法体的方法 但是需要使用  default修饰
    public default void show(){
        System.out.println("我是一个默认的方法");
    }
}

实现类

java
package com.itheima.interface04;
//默认方法子类可以重写 可以不重写
public class MyClassImpl implements MyInterface {
}

测试

java
package com.itheima.interface04;

public class Demo {
    public static void main(String[] args) {
        MyClassImpl myClass = new MyClassImpl();
        myClass.show();
    }
}

1640571168133

1640571377401

1.7.2 JDK8 之后 接口中允许出现静态方法

作用:接口可以直接调用静态方法

格式:

java
public static 返回值类型 方法名(){
    方法体
}

使用

java
接口名.方法名();  方便    这个方法只属于接口

1640571642194

1.8 JDK9 新特性 (了解)

允许私有方法出现:目的是方便自己调用,不让别人调用

1640571805003

1640571880475

第二章 接口和类的关系

2.1 接口和类之间的三种关系 (重点是看源码的时候用)

  • 类和类之间

    继承关系,java 中类支持单继承,不支持多继承,支持多层继承。

  • 类和接口之间

    实现关系,类实现接口,可以单实现,可以多实现。

  • 接口和接口之间

    继承关系,可以单继承,可以多继承,也能多层继承。

    查看源码

    java
    public class ArrayList<E> extends AbstractList<E>
            implements List<E>, RandomAccess, Cloneable, java.io.Serializable
     在继承一个类的基础上又实现多个接口!!

举例子: 在继承一个类的基础上 实现多个接口。

java
package com.itheima.interface05;

public interface MaYun {

   void taobao();
}

package com.itheima.interface05;

public interface WangJianLin {

    void wanda();
}
package com.itheima.interface05;

public interface LiuQiangDong {

    void jd();
}
package com.itheima.interface05;

public class XinBaDie {

    public void zhongdi(){
        System.out.println("种地种的老棒了~~");
    }
}
package com.itheima.interface05;

public class XinBa extends XinBaDie implements MaYun,LiuQiangDong,WangJianLin{
    @Override
    public void taobao() {
        System.out.println("在淘宝开店");
    }


    @Override
    public void jd() {
        System.out.println("在京东开店");
    }

    @Override
    public void wanda() {
        System.out.println("在万达开店");
    }
}
package com.itheima.interface05;

public class Demo {
    public static void main(String[] args) {
        XinBa xb = new XinBa();
        xb.taobao();
        xb.jd();
        xb.wanda();
        //如果凉凉 回家种地
        xb.zhongdi();
    }
}

2.1 抽象类和接口的区别

抽象类,可以有抽象方法,可以具体方法。

​ 实现部分功能,避免子类重复书写,有些需要子类必须重写,设置抽象方法,让子类必须重写。

​ 提高代码的复用性。

接口,只能有抽象方法,没有具体的方法。

​ 实现该接口的类必须重写方法。

​ 提高代码的扩展性,可以进行多实现,实现多个接口可以!!

在设计层面,抽象类是继承体系中的共性功能。接口是继承体系中的扩展功能。

  • 成员上说

  • 接口中变量变成了常量,不能更改。抽象方法。(新特性 默认 静态 私有)

  • 抽象类中的变量还是变量。抽象方法,非抽象方法.

  • 关系去说

    • 类与类 继承关系 支持单继承 不能多继承,可以多层继承。
    • 类与接口 实现关系 类实现接口 可以单实现,可以多实现。
    • 接口和接口 继承关系 支持单继承,也支持多继承。
  • 设计理念

    • 抽象类 共性功能抽取
    • 接口 扩展性功能抽取

第三章 多态

3.1 概念

自然界,事物的多种形态称为多态。

在 java 中,同一对象,在不同时刻表现出来的不同状态。

1640588966525

多态的前提

  • 有继承或者是实现关系。
  • 一般有方法的重写。
  • 父类引用指向了子类对象

举例

Animal

java
package com.itheima.duotai01;
/*
定义动物类   抽象类
 */
public abstract class Animal {
    //动物叫  每种叫的不一样 是一个抽象方法
    public  void shout(){
        System.out.println("动物都会叫");
    }
}

Lv

java
package com.itheima.duotai01;

public class Lv extends Animal {
    @Override
    public void shout() {
        System.out.println("嗷~~~┗|`O′|┛ 嗷~~~");
    }

    // 驴会 拉磨
    public void lamo(){
        System.out.println("驴转圈拉磨");
    }
}

多态测试

java
package com.itheima.duotai01;

public class Demo {
    public static void main(String[] args) {
//        Lv lv = new Lv();//原本样子即可以叫 又可以拉磨
//        lv.shout();
//        lv.lamo();
        //多态形态  父类引用指向子类对象
        Animal animal = new Lv();
        //表象是  一只动物
        // 本质  一头驴
        animal.shout();
//        animal.lamo();
        // 使用多态  就只能使用父类中声明过的方法  无法使用子类特有的功能
        // 调用叫的方法  会输出什么到控制台
    }
}

1640589618227

结论:

java
在多态的情况下,
   只能调用父类声明过的方法,因为表象是父类类型。
   运行的时候执行的方法是子类的,为什么?
    因为 本质是子类对象,子类重写了父类的方法,形成了覆盖。所以调用执行的是子类的方法。

3.2 多态中成员的访问特点

代码是为了推出结论

java
package com.itheima.duotai02;

public class Fu {
    // 父类中定义一个叫做num的成员变量
    int num = 100;
    public void show(){
        System.out.println("我是 父 show");
    }
}
java
package com.itheima.duotai02;

public class Zi extends Fu {
    //子类中定义名字叫num的成员变量
    int num = 300;
    //子类中定义名字叫num2的成员变量
    int num2 = 200;
    // 重写了父类的show方法
    @Override
    public void show() {
        System.out.println("我是 子 show");
    }
    // 子类特有的方法
    public void method(){
        System.out.println("我是子类特有功能");
    }
}
java
package com.itheima.duotai02;

public class Demo {
    public static void main(String[] args) {
        // 多态形式  父类引用指向子类对象
        Fu fu = new Zi();//表象是父 真实对象是子
        //编译阶段看表象  编译阶段看左边
//        System.out.println((fu.num2);
        System.out.println(fu.num);
        fu.show();//编译不报错 因为父类中有该方法定义
//        fu.method();编译报错 因为父类中没有该方法
        // 你来猜一猜 运行的结果是什么 ?
        // 是100和 子show
        // 方法为啥是子show 因为本质对象是 zi 子已经重写了show方法。

        // 变量结果为什么是100 !!!   因为变量不存在重写!!


    }
}

1640589865126

编译阶段,永远看左边,以左边的类型为主去检查编译的语法。有错误就爆红。

运行阶段,变量看左边,方法看右边。

1640592016071

1640592130894

3.3 多态 的好处和弊端 (代码可以不敲 因为目的是感受扩展性)

多态好处案例(理解至上)

Animal

java
package com.itheima.duotai03;
//父类 抽象父类
public abstract class Animal {
    public abstract void eat();
    public abstract void sleep();
}

Cat

java
package com.itheima.duotai03;

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

    @Override
    public void sleep() {
        System.out.println("猫蜷着睡");
    }
}

Dog

java
package com.itheima.duotai03;

public class Dog extends Animal {
    @Override
    public void eat() {
        System.out.println("狗啃骨头");
    }

    @Override
    public void sleep() {
        System.out.println("狗趴着睡");
    }
}

Tiger

java
package com.itheima.duotai03;

public class Tiger extends Animal {
    @Override
    public void eat() {
        System.out.println("老虎吃肉");
    }

    @Override
    public void sleep() {
        System.out.println("老虎蹲着睡");
    }
}

AinmalShop

java
package com.itheima.duotai03;

public class AnimalShop {

    public Animal getAnimal(int type){

        if(type==1){
            return new Dog();
        }else if(type==2){
            return new Tiger();
        }else{
            return new Cat();
        }
    }


}

Home

java
package com.itheima.duotai03;

public class Home {

    public static void main(String[] args) {
        //我们家里想养小猫小狗
        AnimalShop animalShop = new AnimalShop();

        Animal animal1 = animalShop.getAnimal(3);
        Animal animal2 = animalShop.getAnimal(1);


        feedAnimal(animal1);
        feedAnimal(animal2);
    }

    public static void feedAnimal(Animal animal){
        animal.eat();
        animal.sleep();
    }

//    public static void feedCat(Cat cat){
//        cat.eat();
//        cat.sleep();
//    }
//
//    public static void feedDog(Dog dog){
//        dog.eat();
//        dog.sleep();
//    }
//
//    public static void feedTiger(Tiger tiger){
//        tiger.eat();
//        tiger.sleep();
//    }
}

通过案例 我们发现 有了多态这种特征,

我们多态好处 提升了复用性,扩展性。

一个顶 N 个!!

弊端 子类无法使用 特有的功能。

怎么解决弊端 通过向下转型。

java
子类类型 对象名=(子类类型)父类引用;

如果不进行类型的判断 容易出现 类型转换异常

1640593922451

如何避免这个异常出现呢

在转型之前 进行一个类型的判断

语法如下

java
对象名 instanceof 类名   判断该对象是不是该类型。
java
package com.itheima.duotai04;

public class Demo {
    public static void main(String[] args) {
        //多态形式 玩
        //养了一只动物
        Animal animal = new Cat();//向上转型  小转成大的
       animal.eat();
       animal.sleep();

       //想要小猫玩毛线
//        animal.playMaoXian();
       //因为编译不通过
        // 想要调用 就要进行 向下转型!!---类似于强转
//        Cat cat = (Cat)animal;
//        cat.playMaoXian();
//
//        Dog dog = (Dog)animal;
//        // ClassCastException: com.itheima.duotai04.Cat cannot be cast to com.itheima.duotai04.Dog
//        // 类型转换异常       本质猫对象不能转换成狗对象
//        dog.lookDoor();
        // 能不能在 转换之前 先判断能不能转换  能就转换 不能就不转换
        // 先判断  多态形势下的 animal 本质是什么 是猫可以转换成猫 是狗可以转换成狗
        // 判断的语法用到一个运算符  instanceof
        //  变量 instanceof 类名   判断 该变量是不是该类的 对象
        if(animal instanceof Cat){//判断  animal 本质是不是猫
            Cat cat = (Cat)animal;
            cat.playMaoXian();
        }

        if(animal instanceof Dog){//判断  animal 本质是不是狗
            Dog dog = (Dog)animal;
           dog.lookDoor();
        }
    }
}

3.4 通过坑爹案例 使用多态语法

1640596193828

LiGang

java
package com.itheima.kengdie;
// 李刚是一个老师  教 java基础
public class LiGang {
    int age = 40;//年龄

    public void teach(){
        System.out.println("教java基础");
    }

    public void fishing(){
        System.out.println("工作之余去钓鱼");
    }
}

LiTianYi

java
package com.itheima.kengdie;

public class LiTianYi extends LiGang {

    int age = 20;

    public void teach(){
        System.out.println("教你 连连看");
    }

    public void play(){
        System.out.println("玩 王者农药!");
    }



}

Demo

java
package com.itheima.kengdie;

public class Demo {
    public static void main(String[] args) {
        // 风和日丽 李刚带着小米同学 去钓鱼 家里只有了litianyi
        // Litianyi 打游戏  打不过别人  别人有皮肤 符文 为啥没有 没钱
        //  姚明 --学技术  找李刚   打电话   李天一在家接到电话  给你10W块钱 干
        //  不在 怎么办
        // litainyi装爹
        LiGang lg =  new LiTianYi();//向上转型   多态形式   带上帽子 带上胡子 带上眼镜 穿上父亲的衣服 画画鱼尾纹抬头纹
        // 去姚明家 教java
        System.out.println("看一下年龄:"+lg.age);//成员变量运行看左边

        System.out.println("写代码需要指法 需要灵活使用鼠标 所以先教你做连连看 锻炼你的思维能力");
        lg.teach();//他不会java 会 连连看
       // 方法的运行看右边
        System.out.println("今天先教到这里,准备回家");

        // 想玩游戏
//        lg.play(); 现在是李刚的状态 没有玩游戏功能
        //  李天一 脱去伪装
        // 向下转型
        if(lg instanceof LiTianYi){
            LiTianYi liTianYi = (LiTianYi)lg;

            liTianYi.play();
        }

    }
}

第四章 综合案例

4.1 笔记本案例

需求

1640596284896

实现分析

1640596312080

相关类分析

1640596337312

参考代码:

1640596365076

代码实现

USB 接口

java
package com.itheima.noteboot;
/*
  usb的规则
     接口
     里面 功能是抽象的 不给具体的实现
 */
public interface USB {

    void open();//开启功能
    void close();//关闭功能
}

键盘类

java
package com.itheima.noteboot;
// 键盘实现  USB规则
public class KeyBoard implements USB {
    @Override
    public void open() {
        System.out.println("键盘开启");
    }

    @Override
    public void close() {
        System.out.println("键盘关闭");
    }
}

鼠标类

java
package com.itheima.noteboot;
// 键盘实现  USB规则
public class Mouse implements USB {
    @Override
    public void open() {
        System.out.println("鼠标开启");
    }

    @Override
    public void close() {
        System.out.println("鼠标关闭");
    }
}

笔记本类

java
package com.itheima.noteboot;
//定义笔记本类
public class NoteBook {

    // 运行功能
    public void run(){
        System.out.println("笔记本开始运行了...");
    }

    //使用usb设备功能

    /**
     * 定义方法的口诀
     *    确定返回值
     *         不需要
     *    确定参数列表
     *        需要  用USB设备 具体什么 不清楚 可能是鼠标 可能是键盘  那咋办?
     *            只要设备符合 USB规则就可以
     *          参数类型 写 接口类型!!!
     */
    public void useUSB(USB usb){//方法的参数是一个 接口类型 接口类型有对象吗?本身没有,但是可以接收子类类型对象
        usb.open();
        usb.close();
    }


    //关机
    public void shutDown(){
        System.out.println("笔记本关机了.....");
    }
}

Demo

java
package com.itheima.noteboot;

public class Demo {
    public static void main(String[] args) {
        //创建笔记本对象
        NoteBook noteBook = new NoteBook();
        //能不能运行
        noteBook.run();

        //能不能搞一个鼠标过来
        Mouse mouse = new Mouse();

        //能不能搞一个键盘过来
        KeyBoard keyBoard = new KeyBoard();

        // 笔记本能不能用一下鼠标?
        noteBook.useUSB(mouse);//参数是USB接口类型
       //我可以传递 子类对象  调用过程中出现了多态

        //能不能用键盘
        noteBook.useUSB(keyBoard);

        //关机
        noteBook.shutDown();
    }
}

1640599080927

1640599152859

4.2 运动员案例

需求

1640596432872

需求分析

1640596466262

Released under the MIT License.