多态

理解多态

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

生活中的多态

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

再比如当我们按下键盘中的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运算符
  • 用来判断对象是否满足某个特定类型实例特征,满足则返回true,一般用于if语句中。
  • 实际开发中通常判断某个对象是否是某个类或者其子类的实例,或者是某个接口的实现。
  • 通过instanceof运算符可以保证向下转型的安全性,避免出现类型转换的异常,提高代码的健壮性。

类型转换案例

案例1:实现喂宠物的功能,要求如下

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

案例2:根据条件决定饲养何种宠物

空闲时间多:养狗狗;空闲时间不多:养猫咪
实现方案

结论

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

多态总结
  • 多态是同一个行为具有多个不同表现形式或形态的能力,意味着允许不同类的对象对同一消息做出不同的响应
  • 多态的表现形式(实现方式)为方法重载、方法重写、接口实现
  • 多态作用是消除类型之间的耦合关系,提高程序的灵活性和可扩展性
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,980评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,178评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,868评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,498评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,492评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,521评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,910评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,569评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,793评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,559评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,639评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,342评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,931评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,904评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,144评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,833评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,350评论 2 342

推荐阅读更多精彩内容