java-多态

引子:同一件事交给不同的人去做造成不同的结果。--多态

向上转型

向上转型的三种形态:1.直接赋值;2.函数作形参接收;3.做返回值

来看几个例子:eg1.直接赋值

给出代码可以自己感受一下:

//都是在一个包底下的不同类
package Testdemo1;

public class Animal {
    public String name;
    public int age;
    public Animal(String Name,int Age){
        this.name=Name;
        this.age=Age;
    }
    public void eat(){
        System.out.println("正在吃饭...");
    }
}



package Testdemo1;

public class Bird extends Animal{
    public Bird(String Name,int Age){
        super(Name,Age);
    }
    public void eat(){
        System.out.println("小鸟正在吃饭...");
    }
    public void fly(){
        System.out.println("小鸟正在飞行...");
    }
}


package Testdemo1;

public class Dog extends  Animal{
    public Dog(String Name,int Age){
        super(Name,Age);
    }
    public void eat(){
        System.out.println("小狗正在吃饭...");
    }
    public void  bark(){
        System.out.println("小狗正在吠叫...");
    }
}



package Testdemo1;

public class Test01 {
    public static void main(String[] args) {
        Animal a=new Bird("多芬",5);
        System.out.println(a.name +" "+a.age );
    }
}

eg2.作为函数形参接收子类对象

可以看出,在Test类中又写了一个静态函数fun,其功能是打印对象中的各项数据。形参是Aniaml a,是父类的引用;而main函数中给fun函数传入的参数是子类对象。这就是第二种向上转型。

eg.3 作函数返回值

如图,在FUN函数中创建了一个子类Dog的对象dog,然后返回dog,而函数返回值类型用的是Animal父类。这就是第三种向上转型。

向上转型也有缺点,如不能调用子类中有 但 父类中没有的函数。如下:

怎么解决呢?这就引出了下面的内容:向下转型。

向下转型

为了解决父类对象不能访问子类特有函数or成员变量的问题,向下转型应运而生。

其形式类似于C语言中的强制类型转换。

step1:向上转型(三种形式)

step2:向下转型:子类对象=(父类)父类对象

step3:访问子类特有函数

为了安全保险,我们一般还会引入instanceof来确认父类对象是否是由子类对象向上转型而来:

if(animal instanceof Bird){
    Bird bird = (Bird)animal;
    bird.bark();
}

重载与重写

想要实现动态绑定从而实现多态,就需要了解重写,区分重载和重写的区别。

重载:函数名字相同,但其返回值,形参参数类型或者个数 都可以不同。编译器也主要靠形参个数或类型+返回值类型 来区分调用哪一个函数。

而重写的要求更加严格:函数名,返回值类型,形参类型及个数,都必须一模一样,只有函数体(函数的定义部分)可以自行修改。

如下图:

动态绑定

这是实现多态的重要步骤。

先来看一个现象:

public class Animal {
    public String name;
    public int age;
    public Animal(String Name,int Age){
        this.name=Name;
        this.age=Age;
    }
    public void eat(){
        System.out.println("正在吃饭...");
    }
}

public class Bird extends Animal{
    public Bird(String Name,int Age){
        super(Name,Age);
    }
    public void eat(){
        System.out.println("小鸟正在吃饭...");
    }
    public void fly(){
        System.out.println("小鸟正在飞行...");
    }
}

public class Dog extends  Animal{
    public Dog(String Name,int Age){
        super(Name,Age);
    }
    public void eat(){
        System.out.println("小狗正在吃饭...");
    }
    public void  bark(){
        System.out.println("小狗正在吠叫...");
    }
}

public class Test01 {
    public static void fun(Animal animal){
        animal.eat();
        System.out.println("-----------");
    }
    public static void main(String[] args) {
            Dog dog=new Dog("旺财",8);
            Bird bird=new Bird("多芬",6);
            fun(dog);
            fun(bird);
    }

运行结果:

分析一下以上代码:首先,两个子类里都重写了父类的eat()函数;

其次,main函数中创建了两个子类的对象,在调用fun()函数的时候发生了向上转型(第二类:函数形参接收子类对象)。

明明fun函数中是Animal的对象animal调用了eat()函数,却没有表现Animal类里的eat()方法,而是表现出了子类中eat()方法。--多态

动态绑定:等到程序运行阶段,要根据具体的对象才能确定是对应哪个方法。

对应的,静态绑定:在编译阶段就能确定使用哪个方法,看一下例子:

在调用eat()方法时编译器已经知道dog.eat()要调用Dog的eat()方法,同理bird。

总结:出现动态绑定的必要条件:1.有继承关系;2.子类重写父类方法;3.发生向上转型。

感谢大家观看!欢迎提出建议!

  • 17
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值