java的多态

多态🚩

​ 多态就是多种状态,非固定状态。多态在继承的基础上进一步增加了代码的复用性。根据形参(父类)的实际接收参数不同(子类对象不同),方法运行时就可以实现针对某个具体对象的功能,但是却不用针对每个对象,都重新写一个方法。

方法的多态:

​ 重载和重写体现了方法的多态

对象的多态

​ 对象多态的前提是:两个对象(类)存在继承关系,父类引用指向子类对象

  1. 编译类型看等号的左边运行类型看等号的右边

  2. 一个对象的编译类型和运行类型可以不一致,父类的引用可以指向子类的对象

    例:Animal animal = new Dog(); animal的编译类型是Animal,运行类型是Dog

  3. 编译类型在定义对象时,就确定了,不能改变

  4. 运行类型是可以变化

    例:animal = new Cat(); //animal的运行类型从Dog变成了Cat,编译类型仍然是Animal

多态的向上转型

  1. 本质:父类的引用指向了子类的对象

  2. 语法:父类类型 引用名 = new 子类类型();

  3. 编译类型看左边,运行类型看右边。编译类型在编译时确定,运行类型运行时才确定,而这是两个时刻。

  4. 可以调用父类中的所有成员(需要遵守访问权限),不能调用子类中的特有成员,最终运行效果看子类重写(若有)的具体实现(若未重写,向父类查找)

  5. 为什么不能调用子类中的特有成员?运行类型不是子类类型吗?

    因为在编译阶段,能使用哪些成员,是由编译类型来决定的,此时运行类型还没发挥作用。

    而在具体运行的时候才由运行类型来决定,即先在子类中查找是否有该方法,没有的话向上(父类)查找。

    Animal animal = new Dog();//Dog是Animal的子类
    

    例:animal不能调用Dog特有的成员,运行时要先看Dog类中方法的实现

多态的向下转型

  1. 语法:子类类型 引用名 = (子类类型)父类引用

    Cat cat = (Cat) animal;
    
  2. 只能强转父类的引用,不能强转父类的对象。父类的引用本身指向的是堆中的子类对象,强转以后,多了一个cat 引用变量 指向子类对象,而且是Cat类型的,不是Animal类型的。

  3. 而且强转以前就要求父类的引用必须指向的是当前目标类型的对象

    Animal animal = new Cat(); //即有这条语句才能用上面的强转语句
    
  4. 当向下转型后,可以调用子类类型中的所有成员,因为cat的编译类型此时就是子类类型

  • 属性没有重写之说,属性的值直接看编译类型。方法的具体实现就得看运行类型。

    //Animal里面有name属性,Cat里面也有name属性
    Animal animal = new Cat();
    animal.name;//此时为Animal name的值,因为编译类型是Animal。
    
  • instanceof 比较操作符,用于判断某对象的运行类型是否为某类型或某类型的子类型

    Animal animal = new Cat();
    System.out.println(animal instance of Cat);//true
    System.out.println(animal instance of Animal);//true
    
  • 练习

    public class PolyExercise01
    {
    	public static void main(String[] args)
    	{
    		double d = 13.4: //ok
            long I = (long)d; //ok
            System.out.println();//13
            int in = 5; //ok
            boolean b = (boolean)in; //不对,int -> boolean
            Object obj =Hello; //可以,向上转型
            String objStr = (String)obj; //可以,向下转型
            System.out.println(objStr); // hello
            Object objPri = new Integer(5);//可以,向上转型
            String str =(String)objPri; //错误,指向ClassCastException
            Integer str1 = (Integer)objPri; //可以,向下转型
    	}
    }
    

java 的动态绑定机制—实现多态的基础

  1. 当调用对象方法时,该方法会和该对象的内存地址/运行类型绑定
  2. 当调用对象属性时,没有动态绑定机制,哪里声明,哪里使用

总结:方法看运行类型,属性看编译类型。

public class DynamicBinding
{
    public static void main(String[] args)
    {
        A a = new B();
        System.out.println(a.sum()); //结果是20 + 10 = 30
        System.out.println(a.sum1()); //结果是20 + 10 = 30
    }
}
class A
{
	public int i = 10;
    public int sum()
    {
        return getI() + 10; //会调用子类的方法getI()
    }
    public int getI()
    {
        return i;
    }
}
class B extends A
{
    public int i = 20;
    public int getI()
    {
        return i;
    }
    public int sum1()
    {
        return i + 10;
    }
}

多态的应用

  1. 多态数组

    数组的定义类型为父类类型,里面保存的实际元素类型为子类类型

    Person[] persons = new Person[5];
    persons[0] = new Person("jack"20);
    persons[1] = new Student("marry"18100);
    persons[2] = new student("smith"1930.1);
    persons[3] = new Teacher("scott"3020000) :
    persons[4] = new Teacher("king"5025000);
    for(int i = 0; i < persons.length; i++)
    {
    	persons[i].say(); //由于动态绑定机制,这里会分别调用不同类的say()
        if(persons[i] instanceof Student) //判断persons[i]的运行类型是不是Student
        {
            //如果不强转,是无法调用子类特有的方法的,比如 person[i].study()编译无法通过哦
            ((Student)persons[i]).study();  //向下转型,调用Student类特有的方法
        }
    }
    
  2. 多态参数

    方法定义的形参类型为父类类型,实参类型允许为子类类型,实际运行时进行动态绑定。

    class Master
    {
        public String name;
        public void feed(Animal animal, Food food)  //这里可以传入Animal的子类和Food的子类
        {
            System.out.println(animal.getName() + " 在吃 " + food.getName());
        }
    }
    Master master = new master("主人");
    Dog dog = new Dog("大黄");  //Dog是Animal的子类
    Bone bone = new Bone("大棒骨");  //Bone是Food的子类
    master.feed(dog, bone);  //feed方法可以传入形参的子类
    //结果:大黄 在吃 大棒骨
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值