多态

简单入门

022多态 - 图1

代码当中体现多态性,其实就是一句话: 父类引用指向子类对象。

格式:
父类名称对象名= new子类名称();
或者:
接口名称对象名= new 实现类名称();

  1. public class Fu {
  2. public void method() {
  3. System.out.println("父类方法");
  4. }
  5. public void methodFu() {
  6. System.out.println("父类特有");
  7. }
  8. }
  1. public class Zi extends Fu {
  2. @Override
  3. public void method( ) {
  4. System.out.println("子类方法");
  5. }
  6. }
  1. public static void main(String[] args) {
  2. //使用多态的写法
  3. //左侧父类的引用,指向了右侧子类的对象
  4. //new的是谁用的就是谁 ,没有则向上找
  5. Fu obj = new Zi();//子类方法
  6. obj.method();
  7. obj.methodFu();//父类特有方法
  8. }

多态的正常写法,记忆与继承一样

访问成员变量的两种方式:
1.直接通过对象名称访问成员变量:看等号左边是谁,优先用谁,没有则向上找

2.间接通过成员方法访问:看该方法属于谁,优先用谁,没有则向上找

  1. public class Fu {
  2. int num = 10;
  3. public void showNum() {
  4. System.out.println(num);
  5. }
  6. }
  1. public class Zi extends Fu {
  2. int num = 20;
  3. int age = 16;
  4. public void showNum() {
  5. System.out.println(num);
  6. }
  7. }
  1. /*
  2. 访问成员变量的两种方式:
  3. 1.直接通过对象名称访问成员变量:看等号左边是谁,优先用谁,没有则向上找
  4. 2. 间接通过成员方法访问:看该方法属于谁,优先用谁,没有则向上找
  5. */
  6. public static void main(String[] args) {
  7. //使用多态的写法,父类引用指向子类对象
  8. Fu obj = new Zi();
  9. System.out.println(obj.num);
  10. // obj.showNum();//子类没有覆盖重写,就是父: 10
  11. obj.showNum(); //子类覆盖重写,就是子: 20
  12. }

多态成员方法的访问规则

看new的是谁,就优先用谁,没有则向上找。

编译看左边,运行看右边。

  1. public class Fu /*extends object*/ {
  2. int num = 10;
  3. public void showNum() {
  4. System.out.println(num);
  5. }
  6. public void method() {
  7. System.out.println("父类方法");
  8. }
  1. public class Zi extends Fu {
  2. int num = 20;
  3. int age = 16;
  4. @Override
  5. public void showNum() {
  6. System.out.println(num);
  7. @Override
  8. public void method () {
  9. System.out.println("子类方法");
  10. }
  11. public void methodZi () {
  12. System.out.println("子类特有方法");
  13. }
  14. }
  1. public static void main(String[] args) {
  2. Fu obj = new Zi(); //多态
  3. obj. method(); //父子都有,优先用子
  4. obj. methodFu(); //子类没有,父类有,向上找到父类
  5. }

成员变量成员方法对比

成员变量:编译看左边,运行还看左边。
成员方法。编译看左边,运行看右边。

多态的好处

个人理解:父类指向任意子类 通用一个方法
何意? 我只想要work方法 ,所有的教师 助教 都是我的员工
我就让 我的 “员工” work();

022多态 - 图2

多态的转型

向上转型
向下转型

向上转型

1.对象的向上转型,其实就是多态写法:
格式:父类名称对象名= new子类名称0;
Animal animal = new Cat();
含义:右侧创建一 个子类对象,把它当做父类来看待使用。
创建了一只猫,当做动物看待,没问题。
注意事项:向上转型一定是安全的。
从小范围转向了大范围,从小范围的猫,向上转换成为更大范围的动物。
类似于:
double num = 100; //正确,int —> double, 自动类型转换。

  1. public abstract class Animal {
  2. public abstract void eat();
  3. }
  1. public class Cat extends Animal {
  2. @Override
  3. public void eat() {
  4. System.out.println("猫吃鱼");
  5. }
  6. }
  1. /*向上转型一定是安全的,没有问题的,正确的。
  2. 但是也有-一个弊端:对象一旦向上转型为父类,那么就无法调用子类原本特有的内容。
  3. 解决方案:用对象的向下转型[还原]*/
  4. public static void main(String[] args) {
  5. // 对象的向上转型,就是:父类引用指向之类对象。
  6. Animal animal = new Cat();
  7. animal.eat();//猫吃鱼
  8. }
  9. }

向下转型

对象的向下转型,其实是一个[还原]的动作。
格式:子类名称对象名= (子美名称)父类对象:
含义:将父类对象,[还原] 成为本来的子类对象。
Animal animal = new Cat0; //本来是猫,向上转型成为动物
Cat cat = (Cat) animal;本来是猫,已经被当做动物了,还原回来成为本来的猫
注竞事项:
a.必须保证对象本来创建的时候,就是猫,才能向下转型成为猫。
b.如果对象创建的时候本来不是猫,现在非要向下转型成为猫,就会报错。

  1. public abstract class Animal {
  2. public abstract void eat();
  3. }
  1. public class Cat extends Animal {
  2. @Override
  3. public void eat() {
  4. System.out.println("猫吃鱼");
  5. }
  6. public void catMouse() {
  7. System.out.println("猫抓老鼠");
  8. }
  9. }
  1. public class Dog extends Animal {
  2. @Override
  3. public void eat() {
  4. System.out.print1n("狗吃SHIT");
  5. public void watchHouse () {
  6. System.out.print1n("狗看家");
  7. }
  8. }
  9. }
  public static void main(String[] args) {
        // 对象的向上转型,就是:父类引用指向之类对象。
        Animal animal = new Cat(); //本来创建的时候是一只猫
        animal.eat(); //猫吃鱼
        animal.catchMouse(); //错误写法!
//向下转型,进行“还原”动作
        Cat cat = (Cat) animal;
        cat.catchMouse(); //猫抓老鼠
//下面是错误的向下转型
//本来new的时候是一只猫,现在非要当做狗
//错误写法!编译不会报错,但是运行会出现异常:
// java. lang. ClassCastException,类转换异常
        Dog dog = (Dog) animal;


    }

如何才能知道一个父类引用的对象,本来是什么子类?

格式:
对象instance of 类名称
这将会得到一个boolean值结果, 也就是判断前面的对象能不能当做后面类型的实例。

 public static void main(String[] args) {
        Animal animal = new Dog(); //本来是一只狗
        animal.eat(); //狗吃SHIT
        //如果希望掉用子类特有方法,需要向下转型
        //判断一下父类引用animal本来是不是Dog
        if (animal instanceof Dog) {
            Dog dog = (Dog) animal;
            dog.watchHouse();
        }
        //判断一下animol本来是不是Cat
        if (animal instanceof Cat) {
            Cat cat = (Cat) animal;
            cat.catchMouse();
        }
        giveMePet(dog)
    }

    //使用方法
    public static void giveMeAPet(Animal animal) {
        if (animal instanceof Dog) {
            Dog dog = (Dog) animal;
            dog.watchHouse();
            if (animal instanceof Cat) {
                Cat cat = (Cat) animal;
                cat.catchMouse();
            }

        }

接口多态的综合案例

3.1笔记本电脑
笔记本电脑(laptop) 通常具备使用USB设备的功能。在生产时,笔记本都预留了可以插入USB设备的USB接口,
但具体是什么USB设备,笔记本厂商并不关心,只要符合USB规格的设备都可以。
定义USB接口,昊备最基本的开启功能和关闭功能。鼠标和键盘要想能在电脑上使用,那么鼠标和键盘也必须遵守
USB规范,实现USB接口,否则鼠标和键盘的生产出来也无法使用。
3.2案例分析
进行描述笔记本类,实现笔记本使用USB鼠标、USB犍盘
●USB接口,包含打开设备功能、关闭设备叻能
●笔记本类,包含开机功能、关机功能、使用USB设备功能
●鼠标类,要实现USB接口,并具备点击的方法
●键盘类,要守现UsB接口, 且各敲击的方法

022多态 - 图3

USB 接口类

public interface USB {
public abstract void open(); //打开设备
public abstract void close(); //关闭设备
}

computer电脑类

public class Computer {
    public void power0n() {
        System.out.println("笔记本电脑开机");
    }

    public void powerOff() {
        System.out.println(“笔记本电脑关机");
    }

    //使用USB设备的方法,使用接口作为方法的参数
    public void useDevice(USB usb) {
        usb.open(); //打开设备
        if (usb instanceof Mouse) { //-定要 先判断
            Mouse mouse = (Mouse) usb; //向下转型
            mouse.click();
        } else if (usb instsnceof Keyboard){ //先判断
            Keyboard keyboard = (Keyboard) usb; //向下转型
            keyboard.type();
        }
        usb.close();//关闭设备
    }
}

Mouse类

//鼠标就是一 个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("鼠标点击);

    }
}

Keyboard类

//键盘就是一 个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("健盘输入");
    }

}

实现类

 public static void main(String[] args) {
        //首先创建-一个笔记本电脑
        Computer computer = new Computer();
        computer.power0n();
/*一般向上转型写法
准备一个鼠标,供电脑使用
Mouse, mouse = new Mouse();
Useb usbMouse = mouse
    */
//首先进行向上转型
        USB usbMouse = new Mouse(); //.多态写法
//参数是usB类型,我正好传递进去的就是usB鼠标
        computer.useDevice(usbMouse);
//创建一个USB键盘
        Keyboard keyboard = new Keyboard(); //没有使用多态写法
//方法参数是USB类型,传递进去的是实现类对象
        computer.useDevice(keyboard); /正确写法 !
                computer.power0ff();
    }