多态详解 10/07

多态

多态:同一个对象具有多种形态】

作用:把不同的数据类型进行统一;给予程序极高的可扩展性

多态意味着父类型的变量可以引用子类型的对象,向上转型,但本质不变

(子类有对应方法则执行子类方法,没有则执行父类方法——>继承的影响)

动态编译

分类:具体类多态,抽象类多态,接口多态

前提:

  • 有继承或者实现关系

  • 有方法重写

  • 有父类的引用指向子类对象:

- 可以将一个子类的对象赋值给父类(向上转型)

- 但是不可以将父类的对象赋值给子类

成员的访问特点

 Person s2 = new Student();

1.特点总结:

成员变量:编译看左边,执行看左边

成员方法:编译看左边(父类),执行看右边(子类)

不能执行只有子类中有,而父类中没有的方法,编译不会通过

可以执行只有父类中有,而子类中没有的方法(子类继承父类的方法)

2.原因:

  • 成员方法有重写,成员变量没有

3.代码实验

public class Animal {
    public int age = 40;
    public void eat(){
        System.out.println("动物吃东西");
    }
}
public class Cat extends Animal{
    public int age = 20;
    public int weight =10;
​
    @Override
    public void eat() {
        System.out.println("猫吃鱼");
    }
​
    public void playGame(){
        System.out.println("猫玩捉迷藏");
    }
}
public class demo {
    public static void main(String[] args) {
        Animal a = new Cat();
​
​
        System.out.println(a.age);    // 40,调用的是父类中的成员变量
        System.out.println(a.weight);    // 编译不通过,父类中没有该变量   
        a.eat();                      //猫吃鱼,调用的是子类的中的成员方法
        ??a.playGame();                //编译不通过,父类中没有该方法  
    }
}

4.好处与弊端

优点:

  • 具体体现:当定义方法的时候,使用父类作为参数,将来使用的时候,使用具体的(可能重写)子类进行操作

弊端:

  • 不能使用子类的特有功能

应用场景一

父类

public class Animal {
    public void eat(){
        System.out.println("动物吃东西");
    }
}

子类

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

动物操作类

public class AnimalOperator {
​
//    public void useAnimal(Cat c ){c.eat();}
//    public void useAnimal(Dog d){d.eat();}
​
    public void useAnimal(Animal a){
        a.eat();
    }
​
}

执行

public class demo {
    public static void main(String[] args) {
        AnimalOperator animalOperator = new AnimalOperator();
        Cat c = new Cat();
        animalOperator.useAnimal(c);
​
        Dog d = new Dog();
        animalOperator.useAnimal(d);
    }
}

当调用animalOperator.useAnimal(c);时,将 Cat c 传入操作类的方法参数中:

由于猫继承了动物,猫也是动物:

等价于

Aniaml a = new Cat();

即多态的形式,调用方法时,编译看左,执行看右,调用的是子类的方法

具体体现:当定义方法的时候,使用父类作为参数,将来使用的时候,使用具体的(可能重写)子类进行操作

作用:当加入更多类的动物(子类)时,不用一次次修改AnimalOperator类中的方法参数,直接传入父类的引用

  • 极高的可扩展性

应用场景二

经理类继承雇员类(经理也是雇员)

当需要雇员列表时,

  • 需要全部雇员,包括经理

  • 列表中全部元素为同一个类型

多态中的转型

例子

public class demo {
    public static void main(String[] args) {
​
​
        //向上转型
        Animal a = new Cat();
        Animal a1 = new Animal();
        a.eat();
//        a.playGame();
​
​
​
        //向下转型
        Cat c = (Cat) a;           //强制转型,将一个父类的对象强制转化成子类,可以使用子类的方法
        Cat c1 = (Cat) a1;          //报错,ClassCastException,因为a1本来就不是猫类
        c.eat();
        c.palyGame();
        
        System.out.println(a);     //com.oop.demo07duotai.Cat@1b6d3586
        System.out.println(c);     //com.oop.demo07duotai.Cat@1b6d3586
​
        //说明ac是同一个对象
public class Cat extends Animal{
    @Override
    public void eat() {
        System.out.println("猫吃鱼");
    }
​
    public void palyGame(){
        System.out.println("猫捉迷藏");
    }
​
}
public class Animal {
    public void eat(){
        System.out.println("动物吃东西");
    }
​
}

注意

  • 只能在继承层次里进行类型转换

  • 善于使用instanceof进行检查

如,可以使用    
​
if (a instanceof cat){
     Cat c = (Cat) a; 
}

总结

  • 将一个子类的引用赋给父类,编译器是允许的(Animal a = new Cat(); )

  • 但是将一个父类的引用赋给子类变量是不允许的,必须进行类型转换(但是不能随意转,要判断检查)

类型转换的唯一原因:

  • 在暂时忽略了对象的实际类型后(多态性的好处,向上转型便于扩展),现在需要对象的原本的全部功能

  • 现在需要将对象转换为他该是的类型(向下转型,解决多态弊端),以使用子类中特有的方法

内存分析

黑马程序员全套Java教程Java基础入门视频教程,零基础小白自学Java必备教程哔哩哔哩_bilibili

P173

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值