4.多态

目录

4.多态

4.1.多态概述

4.2.多态格式

4.3.多态中成员变量访问特点

4.4.多态中成员方法访问特点

4.5.多态好处

4.6.对象向上向下转型

4.7.多态练习


4.多态

4.1.多态概述

4.2.多态格式

  • 代码当中体现多态性,其实就是一句话,父类引用指向子类对象。
  • 格式:
    • 父类名称 对象名称=new 子类名称();
    • 接口名称 对象名=new 实现类名称();
package demo22.multi;
public class Fu {
    public void method(){
        System.out.println("这是父类method方法");
    }
    public void methodFu(){
        System.out.println("这是父类独有方法");
    }
}


package demo22.multi;
public class Zi extends Fu{
    @Override
    public void method(){
        System.out.println("这是子类method方法");
    }
}


package demo22.multi;
public class Demo01 {
    public static void main(String[] args) {
        //使用多态写法
        Fu o=new Zi(); //左侧父类引用,指向右侧子类对象(猫是动物说法没问题)
        o.method(); //多态中方法访问特点:new谁就访问谁中的方法,没有则向上
        o.methodFu();
    }
}

4.3.多态中成员变量访问特点

  • 多态中成员变量的使用特点:和继承中一致,等号左侧是谁则就优先使用谁,没有则向上找
  • 访问成员变量两种方法:
    • 1.直接通过对象名称访问成员变量,看等号左边是谁则优先用谁,没有则向上找
    • 2.间接通过成员方法访问成员变量,看该方法属于谁则优先用谁,没有则向上找
package demo23_multi;
public class Fu {
    int num=10;
    public void showNum(){
        System.out.println(num);
    }
}

package demo23_multi;
public class Zi extends Fu {
    int num=20;
    int age=30;

    @Override
    public void showNum(){
        System.out.println(num);
    }
}


package demo23_multi;
public class Demo01 {
    public static void main(String[] args) {
        //使用多态写法,父类引用指向子类对象
        Fu o=new Zi();
        System.out.println(o.num);//优先到Fu类中访问num,10
        //System.out.println(o.age);//优先到Fu类中找age,没有则向上找Object类中也没有
        o.showNum();//20,方法属于等号右侧Zi中,没有则在向上找
    }
}

4.4.多态中成员方法访问特点

  • 多态中成员方法使用特点:在多态代码中,成员方法的访问规则:看new的是谁,就优先访问谁,没有则向上找。
  • 口诀:编译看左边,运行看右边。编译指将java代码编译成字节码文件
  • 对比一下:
    • 成员变量:编译看左边,运行还看左边
    • 成员方法:编译看左侧,运行看右侧
       

4.5.多态好处

  • 无论右边new的时候换成哪个子类对象,等号左边不需改变。
  • 多态中成员方法访问特点:编译看左边,运行看右边,
    • 即等号左边父类Employee中必须包含要调用的成员方法work()否则编译报错,另外运行work()方法是看等号右侧中work方法,没有则向上。我们现在唯一要做的就是调用work方法,其他不关系,在使用多态后只需要修改等号右侧子类对象便可调用不同的work方法,等号左侧是不需要修改。
package demo25_multi;

public abstract class Employee {
    public abstract void work();
}

package demo25_multi;
public class Teacher extends Employee {
    @Override
    public void work() {
        System.out.println("讲课");
    }
}

package demo25_multi;
public class Student extends Employee {
    @Override
    public void work() {
        System.out.println("写作业");
    }
}

package demo25_multi;
public class Demo01 {
    public static void main(String[] args) {
        //若不用多态,只用子类,那么写法是
        Teacher teacher = new Teacher();
        teacher.work();//讲课
        Student student = new Student();
        student.work();//写作业

        //现在唯一要做的事情就是调用work方法,其他功能不关心

        //若使用多态写法:
        Employee teacher1=new Teacher();
        teacher1.work();
        Employee student1=new Student();
        student1.work();

    }
}

4.6.对象向上向下转型

  1. 一.对象的向上转型,其实就是多态写法
  • 格式:父类名称 对象名=new 子类名称();   Animal animal=new Cat();
  • 含义:创建子类对象当做父类来看待使用。   创建一只猫,当做动物看待
  • 注意事项:向上转型一定是安全的,从小范围的猫转向大范围动物。
  • 弊端:对象向上转型一定是安全的,对象一旦向上转型为父类,就无法调用子类原本特有内容。创建一只猫对象,向上转型成父类动物对象,猫对象中的特有的捉老鼠方法就不能被访问(不是每个动物都会捉老鼠),
  • 解决方法:用对象的向下转型(即还原)

 

    2.二.对象的向下转型,其实就是一个【还原】的动作

  • 格式:子类名称 对象名=(子类名称)父类对象
  • 含义:将父类对象【还原】成为本来的子类对象
  • Animal animal=new Cat();//本来是猫,向上转型成为动物
  • Cat cat=(Cat)animal;//本来是猫,已经被当做动物了,现还原回来成本来的猫
  • 注意事项:
    • 1.必须保证对象本来创建的时候,就是猫,才能向下转型为猫
    • 2.如果对象创建时候本来不是猫,现在非要向下转型成为猫,就会报错。
    • 3.如何保证对象正常的向下转型:使用instanceof关键字。

 */
 

   3.如何保证对象安全的上下转型--使用关键字instanceof

  • 如何才能知道一个父类引用的对象,本来是什么子类(Cat/Dog)?
  •  格式:对象 instanceof 类名称,这会返回一个布尔值,判断该对象是否是该类的实例


   4.应用:

  • 写一个送宠物的方法,什么宠物不一定,所以方法参数使用父类引用(对象向上转型), 这样任何子类对象(宠物)都可以传过来而方法参数不需要改动,这就是多态好处,父类下的任何子类对象都可以被接收到父类引用对象animal中,不需要频繁变动参数类型。这样向上转型的一个弊端就是无法访问子类独有方法,这就需要在使用的时候将对象向下转型
package demo26.multi;
public abstract class Animal {
    public abstract void eat();
}

package demo26.multi;
public class Cat extends Animal{
    @Override
    public void eat() { //重写父类抽象方法eat
        System.out.println("猫吃鱼");
    }
    //子类特有方法
    public void catchMouse(){
        System.out.println("猫捉老鼠");
    }
}


package demo26.multi;
public class Dog extends Animal {
    @Override
    public void eat() {//重写父类抽象方法
        System.out.println("狗吃骨头");
    }
    //该子类特有的方法
    public void watchHouse(){
        System.out.println("狗看家");
    }
}


package demo26.multi;
public class Demo01 {
    public static void main(String[] args) {
        //对象的向上转型,就是,父类引用指向子类对象(也是多态写法)
        Animal animal=new Cat();
        animal.eat();//猫吃鱼
        //animal.catchMouse();错误写法,向上转型的对象无法访问子类特有方法,需向下转型

        //向下转型,进行还原动作
        Cat cat=(Cat)animal;
        cat.catchMouse(); //猫捉老鼠  缩写((Cat) animal).catchMouse();

        //下面是错误的向下转型
        //本来new的时候后是一只猫,现在非要转型成狗
        //错误写法,编译不会报错,但是运行会出现异常java.lang.ClassCastException类转换异常
        //Dog dog=(Dog)animal;
    }
}


package demo26.multi;
public class Demo02 {
    public static void main(String[] args) {
        Animal animal=new Cat();
        animal.eat(); //父类引用的对象只能访问共有的方法,也就是父类有的并在子类重写的

        //如果希望调用子类特有方法,需要向下转型
        //判断父类引用对象animal本来是不是属于子类Dog的实例
        if (animal instanceof Dog){
            //是则可以安全向下转型成Dog类对象
            Dog dog=(Dog)animal;
            dog.watchHouse();
        }
        if (animal instanceof Cat){
            Cat cat = (Cat) animal;
            cat.catchMouse();
        }

      }

    public static void giveMePet(Animal animal){
        //判断父类引用对象animal本来是不是属于子类Dog的实例
        if (animal instanceof Dog){
            //是则可以安全向下转型成Dog类对象
            Dog dog=(Dog)animal;
            dog.watchHouse();
        }
        if (animal instanceof Cat){
            Cat cat = (Cat) animal;
            cat.catchMouse();
        }
    }
}

4.7.多态练习

package demo27.multi;
//定义USB接口
public interface USB {
    public abstract void open();//开启设备
    public abstract void close();//关闭设备
}


package demo27.multi;
//鼠标是一个USB设备
public class Mouse implements USB {
    @Override
    public void open() {//重写父类抽象方法
        System.out.println("打开鼠标");
    }

    @Override
    public void close() {//重写父类抽象方法
        System.out.println("关闭鼠标");
    }

    public void click(){ //子类独有方法
        System.out.println("鼠标点击");
    }
}

package demo27.multi;
//键盘是一个USB设备
public class Keyboard implements USB {
    @Override
    public void open() { System.out.println("打开键盘");}

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

    public void type(){ System.out.println("敲键盘");//子类独有键盘 }
}


package demo27.multi;
//电脑类
public class Computer {
    public void powerOn(){ System.out.println("开机"); }
    public void powerOff(){ System.out.println("关机"); }
    //电脑使用USB设备的方法,使用接口作为方法参数(多态),具体什么设备不知奥
    public void usbDevice(USB usb){
        usb.open();//打开usb设备
        if (usb instanceof Mouse){//判断设备是鼠标,向下转型才能调用子类(鼠标)中独有方法
            Mouse mouse=(Mouse)usb;
            mouse.click();
        }else if(usb instanceof Keyboard){
            Keyboard keyboard = (Keyboard) usb;
            keyboard.type();
        }
        usb.close();//关闭Usb设备
    }
}


package demo27.multi;
public class Demo01 {
    public static void main(String[] args) {
        //创建电脑
        Computer computer = new Computer();
        computer.powerOn();//开机

        //准备USB设备鼠标,供电脑使用
        USB usbMouse=new Mouse();//对象向上转型
        computer.usbDevice(usbMouse);//电脑使用鼠标设备;参数是USB类型,传递就是USB鼠标
        computer.powerOff();

        //准备USB设备键盘,共电脑使用
        Keyboard keyboard = new Keyboard();
        //方法参数是USB接口类型,传递进去的实现类对象(多态写法也是对象向上转型)
        computer.usbDevice(keyboard);//发生了向上转型
        computer.powerOff();
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值