Java学习笔记@多态

笔者:unirithe

日期:11/09/2021

多态

同类型的对象,执行同一个行为,表现出不同的行为特征

常见形式

父类类型 对象名称 = new 子类构造器;
接口 对象名称 = new 实现类构造器;
abstract class Animal{
    public void run(){}
}
class Dog extends Animal{
    @Override
    public void run() {
        System.out.println("小狗跑");
    }
}
class Demo{
    public static void main(String[] args) {
            Animal d = new Dog();
            d.run();
    }
}

成员访问特点

  • 方法调用:编译看左,运行看右
  • 变量调用:编译看左,运行也看左

(多态侧重行为多态)

import com.sun.xml.internal.ws.api.model.wsdl.WSDLOutput;

class Animal{
    public String type = "动物";
    public void printType(){
        System.out.println(this.type);
    }
}
class Dog extends Animal{
    public String type = "小狗";
    @Override
    public void printType() {
        System.out.println(this.type);
    }
}
class Demo{
    public static void main(String[] args) {
        Animal a = new Dog();
        System.out.println(a.type);  // 调用变量,输出:动物
        a.printType();               // 调用方法,输出: 小狗
    }
}

多态前提

  • 继承 / 实现关系
  • 有父类引用指向子类对象
  • 有方法重写

多态优势

解耦合

在多态形势下,右边对象可以实现解耦合,便于扩展和维护

Animal a = new Dog();
a.run();
// 后续业务行为随new的对象而变,后续代码无需修改

高扩展与便利

定义方法时使用父类型作为参数,该方法就可以接受父类的一切子类对象

import com.sun.xml.internal.ws.api.model.wsdl.WSDLOutput;

abstract class Animal{
    void run(){};
}
class Dog extends Animal{
    @Override
    void run() {
        System.out.println("小狗跑");
    }
}
class Demo{
    public static void main(String[] args) {
            Animal a = new Dog();
            go(a);
    }
    public static void go(Animal a){
        System.out.println("开始");
        a.run();
        System.out.println("结束");
    }
}

多态的问题 :多态下不能使用子类的独有功能

类型转换

自动类型转换(从子到父)

子类对象赋值给父类类型的变量指向

强制类型转换(从父到子)

此时必须进行强制类型转换,即子类 对象变量 = (子类) 父类类型的变量

作用:解决多态下的劣势,可实现调用子类独有的功能

注意:如果转型后的类型和对象真实类型不是同一种类型,那么在转换的时候就会出现ClassCastException,例如:

Animal a = new Cat();
Dog b = (Dog) a; // 报错

防止出现这个问题可以在转换前使用 instanceof 判断当前对象的真实类型

变量名 instanceof 真实类型

判断关键字左边的变量指向的对象的真实类型,是否是右边的类型或其子类类型,则返回true,否则返回false

Animal a = new Cat();
Dog b = null;
if (a instanceof Dog)
    b = (Dog) a;

总结

  • 引用数据类型的类型转换的两种方式
    • 自动类型转换
    • 强制类型转换
  • 强制类型转换解决什么问题?需要注意什么?
    • 可转换成真正的子类类型,从而调用子类独有功能
    • 有继承 / 实现的 2个类型就可以进行类型转换,编译无问题
    • 运行时,若发现强制转换的类型不是对象真实类型则报错
    • 类型转换异常:ClassCastException

多态案例(USB设备)

需求: 使用面向对象编程,设计可安装2个USB设备的电脑对象

  • 鼠标:被安装时可接入、点击、拨出
  • 键盘:被安装时刻接入、打字、拨出

分析:

  • USB接口:接入和拔出
  • USB实现类:分别表示鼠标和键盘,实现USB接口
  • 电脑对象:创建2个USB实现类对象
import java.security.Key;

interface USB{
    void connect();
    void unConnect();
}
class KeyBoard implements USB{
    private String name;

    public KeyBoard(String name) {
        this.name = name;
    }

    @Override
    public void connect() {
        System.out.println(name + " 连接成功!");
    }

    @Override
    public void unConnect() {
        System.out.println(name + " 断开连接!");
    }
    public void onKnock(){
        System.out.println(name + "敲击了一下.");
    }
}

class Mouse implements USB{
    private String name;

    public Mouse(String name) {
        this.name = name;
    }

    @Override
    public void connect() {
        System.out.println(name + " 连接成功!");
    }

    @Override
    public void unConnect() {
        System.out.println(name + " 断开连接!");
    }
    public void onClick(){
        System.out.println(name + " 点击了一下.");
    }
}
class Computer{
    private String name;

    public Computer(String name) {
        this.name = name;
    }
    public void connectUSB(USB usb){ // 多态
        usb.connect();
        if(usb instanceof KeyBoard) {
            KeyBoard k = (KeyBoard) usb;
            k.onKnock();
         } else if (usb instanceof Mouse){
            Mouse m = (Mouse) usb;
            m.onClick();
        }
    }
    public void start(){
        System.out.println(name + " 启动成功!");
    }
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
class Demo{
    public static void main(String[] args) {
        Computer c = new Computer("笔记本");
        c.start();
        USB u1 = new KeyBoard("机械键盘");
        c.connectUSB(u1);
        USB u2 = new Mouse("鼠标");
        c.connectUSB(u2);
    }
}
posted @ 2021-11-09 09:05  Unirithe  阅读(61)  评论(2)    收藏  举报