多态

多态

面向对象:封装,继承,多态

extends继承或者implements实现,是多态性的前提

小明是一个学生,也是一个人。一个对象拥有多种形态,这就是对象的多态性

多态的格式和使用

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

【格式:】

​ 父类名称 对象名 = new 子类名称();

​ 或者

​ 接口名称 对象名 = new 实现类名称();

package Demo13;

public class Fu {
    public void method(){
        System.out.println("父类方法");
    }

    public void methodFu(){
        System.out.println("父类特有");
    }
}
package Demo13;

public class Zi extends Fu {

    @Override
    public void method(){
        System.out.println("子类方法");
    }
}
package Demo13;

public class Multi {

    public static void main(String[] args) {
        //使用多态的写法
        //左侧父类的引用,指向了右侧子类的对象
        Fu obj = new Zi();

        obj.method();
        obj.methodFu();

    }
}
访问成员变量的两种方式
  1. 直接通过对象名称访问成员变量,看等号左边是谁,优先用谁,没有 向上找
  2. 间接通过成员方法访问成员变量,看该方法属于谁,优先用谁,没有 向上找
package Demo14;

public class Fu {
    int num = 10;

    public void showNum(){
        System.out.println(num);
    }
}
package Demo14;

public class Zi  extends Fu{
    int num = 20;

    int age = 20;

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

public class Muntifield {
    public static void main(String[] args) {
        //使用多态的方法,父类引用指向子类对象
        Fu obj = new Zi();
        System.out.println(obj.num);
        //错误写法,父类里没有age
//        System.out.println(obj.age);

        //子类没有覆盖重写,就是父 10
        //子类如果覆盖重写,就是子20
        obj.showNum();
    }
}
多态中成员方法的使用特点
  • 在多态代码中,,成员方法的访问规则是:

    • 看new的是谁,就优先用谁,没有则向上找
  • 口诀:

    • 编译看左边,运行看右边4
  • 对比:

    • 成员变量:编译看左边,运行还看左边
    • 成员方法:编译看左边,运行看右边
package Demo14;

public class MultMethod {
    public static void main(String[] args) {
        Fu obj = new Zi(); //多态

        obj.method(); //父子都有,优先用子
        obj.methodFu(); //子类没有,父类有,向上找到父类使用

        //编译看左边,左边是是Fu,Fu当中没有methodZi方法,所以报错
//        obj.methodZi(); //错误写法!
    }
}
使用多态的好处

在这里插入图片描述

对象的向上转型
  • 对象的向上转型,其实就是多态写法:

    • 格式:父类名称 对象名 = new 子类名称();
    • 含义:右侧创建一个子类对象,把他当作父类来看待使用
    • 注意事项:向上转型一定是安全的,因为是从小范围转向了大范围。
    • 弊端:一旦向上转型为父类,那么就无法调用子类原本特有的方法

    Animal animal = new Cat(); 从小范围的猫,向上转换成为更大的动物

package Demo14;

public abstract class Animal {

    public abstract void eat();
}

package Demo14;

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

public class Main {
    public static void main(String[] args) {
        //对象的向上转型,就是,父类引用指向子类对象
        Animal animal = new Cat();
        animal.eat();
    }
}
对象的向下转型

向上转型一定是安全的,因为是从小范围转向了大范围。弊端:一旦向上转型为父类,那么就无法调用子类原本特有的方法

解决方案:用对象的向下转型【还原】

  • 对象的向下转型,其实是一个【还原】的动作

  • 格式

    • 子类名称 对象名 = (子类名称)父类对象;
  • 含义

    • 将父类对象,【还原】成为本来的子类对象

    • Animal animal = new Cat(); //本来是猫,向上转型成为动物

      Cat cat = (Cat) animal; //本来是猫,已经被当作动物了,还原回来成为原来的猫

  • 注意事项

    • 必须保证对象本来创建的时候,就是猫,才能向下转型成为猫
    • 如果对象创建的时候本来不是猫,现在非要向下转型成为猫,就会报错java.lang.ClassCastException
package Demo14;

public class Cat extends Animal {
    @Override
    public void eat(){
        System.out.println("猫吃鱼");
    }
    public void catMouse(){
        System.out.println("猫抓老鼠");
    }
}
package Demo14;

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

    public void watchHoyse(){
        System.out.println("狗看家");
    }
}
package Demo14;

public abstract class Animal {

    public abstract void eat();
}
package Demo14;

public class Main {
    public static void main(String[] args) {
        //对象的向上转型,就是,父类引用指向子类对象
        Animal animal = new Cat(); //本来创建的时候就是猫
        animal.eat(); //猫吃鱼

        //向下转型
        Cat cat = (Cat) animal;
        cat.catMouse();

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

    }
}
instanceof关键字

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

  • 格式:

    对象 instanceof类型

    这将会得到一个boolean值结果,也就是判断前面的对象能不能当最后面类型的实例

package Demo14;

public class Demo02Instanceof {
    public static void main(String[] args) {
        Animal animal = new Cat(); //本来是一只猫
        animal.eat(); //猫吃鱼

        //如果希望调用子类特有的方法,需要向下转型
        //判断一下父类animal本来是不是Dog
        if (animal instanceof Dog){
            Dog dog = (Dog) animal;
            dog.watchHoyse();
        }
        //判断一下animal本来是不是Cat
        if (animal instanceof Cat){
            Cat cat = (Cat) animal;
            cat.catMouse();
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值