基础知识

多态

2018-12-02  本文已影响11人  若兮缘

理解多态

多态,即多种形态,面向对象程序设计语言当中最核心的特征,理解多态能帮助我们更好的进行程序设计。

生活中的多态

我们知道动物一般都有吃东西、跑、跳、叫等等一些通用的行为能力,但是不同动物针对这些行为的表现形式是不同的,比如猫、狗、兔子喜欢吃的东西各有不同,它们的叫声也不一样。

再比如当我们按下键盘中的F1键时,针对当前工作窗口的不同它也将会显示不同的帮助文档,比如在eclipse中弹出的是关于eclipse中的帮助文档,在word中就弹出word的帮助文档。

所以可以看出同样一种行为,在不同的对象上会产生不同的显示结果,这就是生活中的多态。

程序中的多态

在程序设计中,多态就意味着允许不同类的对象对同一消息做出不同的响应。广泛意义上而言,多态可以分为:编译时多态和运行时多态。
编译时多态(设计时多态):表现形式为方法重载。
运行时多态:JAVA运行时系统根据调用该方法的实例的类型来决定选择调用哪个方法。我们平时所说的多态大多指的是运行时多态。

多态存在的必要条件
  1. 满足继承关系
  2. 重写方法
  3. 父类引用指向子类对象

多态实现

定义子父类

定义动物父类及猫、狗子类,类的关系图

父类的定义:

/**
 * 动物类
 */
public class Animal {
    //属性:昵称、年龄(省略getter和setter)
    private String name;
    private int month;
    //构造方法
    public Animal(){
        
    }
    public Animal(String name,int month){
        this.name=name;
        this.month=month;
    }
    
    //方法:吃东西
    public void eat(){
        System.out.println("动物都有吃东西的能力");
    }
}

子类的定义:

/**
 * 猫
 */
public class Cat extends Animal{
    //属性:体重
    private double weight;
    //构造方法
    public Cat(){
        
    }
    public Cat(String name,int month,double weight){
        super(name,month);
        this.weight=weight;
    }
    
    //方法:跑动
    public void run(){
        System.out.println("小猫快乐的奔跑");
    }
    //方法:吃东西(重写父类方法)
    @Override
    public void eat() {
        System.out.println("猫吃鱼~~");
    }
}
/**
 * 狗
 */
public class Dog extends Animal {
    //属性:性别
    private String sex;
    //构造方法
    public Dog(){
        
    }
    public Dog(String name,int month,String sex){
        this.setMonth(month);
        this.setName(name);
        this.setSex(sex);
    }
    
    //方法:睡觉
    public void sleep(){
        System.out.println("小狗有午睡的习惯");
    }
    //方法:吃东西(重写父类方法)
    @Override
    public void eat() {
        System.out.println("狗吃肉~~");    
    }
}
向上转型(Upcase)
    public static void main(String[] args) {
        //多态的表现:都使用同一父类对象类型完成同一种行为,表现形式却各不相同
        Animal one = new Animal();
        Animal two = new Cat();
        Animal three = new Dog();
        one.eat(); //动物都有吃东西的能力
        two.eat(); //猫吃鱼~~
        three.eat(); //狗吃肉~~
    }
动态绑定

多态的实现可以通过向上转型和动态绑定机制来完成,向上转型实现了将子类对象向上转型为父类类型,而动态绑定机制能识别出对象转型前的类型,从而自动调用该类的方法,两者相辅相成。
绑定:绑定就是将一个方法调用同一个方法所在的类连接到一起就是绑定。绑定分为静态绑定和动态绑定两种。
静态绑定:在程序运行之前进行绑定(由编译器和链接程序完成的),也叫做前期绑定。
动态绑定:在程序运行期间由JVM根据对象的类型自动的判断应该调用哪个方法,也叫做后期绑定。

静态绑定的例子
如有一类Human,它派生出来三个子类Chinese类、American类和British类,三个子类中都重写了父类中的方法speak(),在测试类中用静态绑定的方式调用方法speak()。

这种调用方式是在代码里指定的,编译时编译器就知道谁调用的是Chinese的speak(),谁调用的是American的speak()。

动态绑定的例子

此时, Human类中随机生成Chinese类、American 类和British 类的对象,编译器不能根据代码直接确定调用哪个类中的speak()方法,直到运行时才能根据产生的随机数n的值来确定human[i]到底代表哪一个子类的对象,这样才能最终确定调用的是哪个类中的speak()方法,这就是动态绑定。

向下转型(Downcast)

向下转型是与向上转型相对的概念,它是用子类引用指向父类实例,必须进行强转,所以向下转型又叫做强制类型转换。
向下转型后就可以调用子类特有的方法了,但是必须满足转型条件才能进行强转。

    public static void main(String[] args) {
        Animal one = new Animal();
        Animal two = new Cat();
        Animal three = new Dog();
        //向下转型
        Cat temp = (Cat)two;
        temp.eat();
        temp.run();
        //类型不匹配无法进行转换,运行时出现异常:ClassCastException
        //如何避免出现该异常?使用instanceof运算符
        Cat temp2 = (Cat)one;
        Dog temp3 = (Dog)two;
    }
instanceof运算符

类型转换案例

案例1:实现喂宠物的功能,要求如下
喂猫咪:吃完东西后(eat方法),主人会带着去玩线球(playBall方法)
喂狗狗:吃完东西后(eat方法),主人会带着狗狗去睡觉(sleep方法)
实现方案:
在喂养动物的种类比较少时,两种方案均可,但是当我们需要实现更多动物的喂养需求时方案1需要增加非常多的方法,而方案2则只需要修改方法体的内部实现,增加相应动物子类的处理方法即可。

案例2:根据条件决定饲养何种宠物
空闲时间多:养狗狗;空闲时间不多:养猫咪
实现方案

结论:在实际的开发当中,如果需要同一个操作行为针对不同条件(参数)返回不同的实例对象,或者完成不同的操作结果时,就可以使用这种多态的方式实现,类型转换的优势就可以充分体现出来了。

多态总结

上一篇 下一篇

猜你喜欢

热点阅读