作者:程序狗
链接:https://www.zhihu.com/question/30082151/answer/120520568
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

用一句话概括就是:事物在运行过程中存在不同的状态。先以教科书般举例说明,下文再举一个花木兰替父从军的例子帮助大家理解. 多态的存在有三个前提:
1.要有继承关系
2.子类要重写父类的方法
3.父类引用指向子类对,
但是其中又有很多细节需要注意。首先我们定义两个类,一个父类Animal,一个子类Cat。
父类Animal

class Animal {int num = 10; static int age = 20; public void eat() { System.out.println("动物吃饭"); } public static void sleep() { System.out.println("动物在睡觉"); } public void run(){ System.out.println("动物在奔跑"); } } 

子类Cat

class Cat extends Animal { int num = 80; static int age = 90; String name = "tomCat"; public void eat() { System.out.println("猫吃饭"); } public static void sleep() { System.out.println("猫在睡觉"); } public void catchMouse() { System.out.println("猫在抓老鼠"); } } 

测试类Demo_Test1

class Demo_Test1 {public static void main(String[] args) { Animal am = new Cat(); am.eat(); am.sleep(); am.run(); //am.catchMouse();这里先注释掉,等会会说明 //System.out.println(am.name);//这里先注释,待会说明 System.out.println(am.num); System.out.println(am.age); } } 

以上的三段代码充分体现了多态的三个前提,即:
1、存在继承关系
Cat类继承了Animal类
2、子类要重写父类的方法
子类重写(override)了父类的两个成员方法eat(),sleep()。其中eat()是非静态的,sleep()是静态的(static)。
3、父类数据类型的引用指向子类对象。
测试类Demo_Test1中 Animal am = new Cat();语句在堆内存中开辟了子类(Cat)的对象,并把栈内存中的父类(Animal)的引用指向了这个Cat对象。
到此,满足了Java多态的的必要三个前提。
---------------------------------------------------华丽的分割线----------------------------------------------------------------------
如果再深究一点呢,我们可以看看上面测试类的输出结果,或许对多态会有更深层次的认识。猜一猜上面的结果是什么。
<img src="https://pic4.zhimg.com/521db7a41065f92441a95b0ff294e707_b.png" data-rawwidth="671" data-rawheight="133" class="origin_image zh-lightbox-thumb" width="671" data-original="https://pic4.zhimg.com/521db7a41065f92441a95b0ff294e707_r.png">可以看出来可以看出来
子类Cat重写了父类Animal的非静态成员方法am.eat();的输出结果为:猫吃饭。
子类重写了父类(Animal)的静态成员方法am.sleep();的输出结果为:动物在睡觉
未被子类(Cat)重写的父类(Animal)方法am.run()输出结果为:动物在奔跑

System.out.println(am.num);//输出结果为10 System.out.println(am.age);//输出结果为20 

那么我们可以根据以上情况总结出多态成员访问的特点:
成员变量
编译看左边(父类),运行看左边(父类)
成员方法
编译看左边(父类),运行看右边(子类)。动态绑定
静态方法
编译看左边(父类),运行看左边(父类)。
(静态和类相关,算不上重写,所以,访问还是左边的)
只有非静态的成员方法,编译看左边,运行看右边
---------------------------------------------------华丽的分割线----------------------------------------------------------------------
那么多态有什么弊端呢?有的,即多态后不能使用子类特有的属性和方法。往上面的代码看,子类Cat有一个特有的属性String name = "tomCat"; 并且还有一个特有的抓老鼠的方法catchMouse()。但是在测试类(Demo_Test)中,我们尝试调用子类特有的方法catchMouse()和打印子类特有的成员属性String name = "tomCat"; 就会报错。

am.catchMouse();
System.out.println(am.name); 

<img src="https://pic3.zhimg.com/a44f349a4179695f223c683d4eddb8a6_b.png" data-rawwidth="302" data-rawheight="223" class="content_image" width="302">原因就是多态的弊端,就是:不能使用子类特有的成员属性和子类特有的成员方法。
--------------------------------------------------华丽的分割线----------------------------------------------------------------------
如果在代码执行过程中还想使用Cat类中特有的属性String name和它特有的成员方法catchMouse()了怎么办呢?那我们就可以把这个父类引用指向了子类对象的家伙am再强制变回Cat类型。这样am就是Cat类型的引用了,指向的也是Cat对象了,自然也能使用Cat类的一切属性和一切的成员方法。

class Demo_Test {public static void main(String[] args) { Animal am = new Cat(); am.eat(); am.sleep(); am.run(); // am.catchMouse(); // System.out.println(am.name); System.out.println(am.num); System.out.println(am.age); System.out.println("------------------------------"); Cat ct = (Cat)am; ct.eat(); ct.sleep(); ct.run(); ct.catchMouse(); } } 

<img src="https://pic3.zhimg.com/b224f6fa488db52088f02d500677448a_b.png" data-rawwidth="677" data-rawheight="234" class="origin_image zh-lightbox-thumb" width="677" data-original="https://pic3.zhimg.com/b224f6fa488db52088f02d500677448a_r.png">很明显,执行强转语句Cat ct = (Cat)am;之后,ct就指向最开始在堆内存中创建的那个Cat类型的对象了。这就是多态的魅力吧,虽然它有缺点,但是它确实十分灵活,减少多余对象的创建,不用说为了使用子类的某个方法又去重新再堆内存中开辟一个新的子类对象。以上。。很明显,执行强转语句Cat ct = (Cat)am;之后,ct就指向最开始在堆内存中创建的那个Cat类型的对象了。这就是多态的魅力吧,虽然它有缺点,但是它确实十分灵活,减少多余对象的创建,不用说为了使用子类的某个方法又去重新再堆内存中开辟一个新的子类对象。以上。。
----------------------------------------------------------分割线------------------------------------------------------------------------
啦啦啦,收到这么多赞.很惊讶,举个通俗点的例子吧.
花木兰替父从军
大家都知道花木兰替父从军的例子,花木兰替父亲花弧从军。那么这时候花木兰是子类,花弧是父类。花弧有自己的成员属性年龄,姓名,性别。花木兰也有这些属性,但是很明显二者的属性完全不一样。花弧有自己的非静态成员方法‘骑马杀敌’,同样花木兰也遗传了父亲一样的方法‘骑马杀敌’。花弧还有一个静态方法‘自我介绍’,每个人都可以问花弧姓甚名谁。同时花木兰还有一个自己特有的非静态成员方法‘涂脂抹粉’。但是,现在花木兰替父从军,女扮男装。这时候相当于父类的引用(花弧这个名字)指向了子类对象(花木兰这个人),那么在其他类(其他的人)中访问子类对象(花木兰这个人)的成员属性(姓名,年龄,性别)时,其实看到的都是花木兰她父亲的名字(花弧)、年龄(60岁)、性别(男)。当访问子类对象(花木兰这个人)的非静态成员方法(骑马打仗)时,其实都是看到花木兰自己运用十八般武艺在骑马打仗。当访问花木兰的静态方法时(自我介绍),花木兰自己都是用她父亲的名字信息在向别人作自我介绍。并且这时候花木兰不能使用自己特有的成员方法‘涂脂抹粉’。-----多态中的向上转型
那么终于一将功成万骨枯,打仗旗开得胜了,花木兰告别了战争生活。有一天,遇到了自己心爱的男人,这时候爱情的力量将父类对象的引用(花弧这个名字)强制转换为子类对象本来的引用(花木兰这个名字),那么花木兰又从新成为了她自己,这时候她完全是她自己了。名字是花木兰,年龄是28,性别是女,打仗依然那样生猛女汉子,自我介绍则堂堂正正地告诉别人我叫花木兰。OMG!终于,终于可以使用自己特有的成员方法‘涂脂抹粉’了。从此,花木兰完全回到了替父从军前的那个花木兰了。并且和自己心爱的男人幸福的过完了一生。-----多态中的向下转型
----------------------------------------------------------华丽的分割线---------------------------------------------------------------
大家记得哈,向上转型向下转型一定是在多态这个前提下哈,否则强制将女儿变成父亲,或者将父亲变成女人,就变成东方不败了,系统此时就会报错非法类型转换。哈哈哈哈哈。另外开发中一般是利用多态声明形式参数,并将创建子类的匿名对象作为实际参数。以上。

转载于:https://www.cnblogs.com/lwj820876312/p/7243227.html

什么是多态,多态的实现方法是什么?相关推荐

  1. python 面向对象_多态、内置方法、反射

    内容: 1.接口思想 2.抽象类思想 3.多态 4.内置方法 5.反射 1.接口思想 建立关联的桥梁,方便管理代码 接口类:用来定义功能的类,位继承它的子类提供功能 该类的功能方法一般不需要实现体,实 ...

  2. C# 中的多态和虚方法,如何实现多态和使用虚方法?

    在 C# 中,多态(Polymorphism)是面向对象编程的基本特性之一,它允许使用不同的对象和方法来执行同一操作.C# 中实现多态的方式主要是通过虚方法和抽象类. 虚方法是一种允许子类覆盖的方法, ...

  3. 一木.溪桥学Python-13:多继承、多态、常用魔法方法、单例模式

    一木.溪桥 在Logic Education跟Amy学Python 逻辑教育 :https://logicedu.ke.qq.com 12期:Python基础课 一木.溪桥学Python-13:多继承 ...

  4. 12.0_[Java 多态]-多态/子类父类互转/基本引用类型互转/ instanceof 运算符

    ################################################## 目录 多态 什么是多态 为什么使用多态 向上转换/子类到父类的转换 使用父类作为方法形参实现多态 ...

  5. 多态 什么是多态 多态转型 注意事项

    关键知识点和补充    封装: 隐藏内部的实现细节,对外提供公共的访问方式   继承: 子类一旦继承父类,就有权使用父类中的内容  多态: 一种事物的多种形态|多种表现形式 多态的前提:  继承    ...

  6. 对多态变形引擎背后方法的概述

    译者注:SMEG(Simulated Metamorphic Encryption Generator)是一个影响颇大的多态变形引擎,它使用的方法受到众人的仿效.虽然本文没有详细介绍SMEG中所使用的 ...

  7. 25 类:接口 抽象父类 多态 鸭子类型 格式化方法与析构方法 反射 异常处理 自定义异常 断言...

    面向对象与面向过程分析 # 清晰知道操作的功能,但不明确操作的具体对象 print(len('123')) # 清晰知道操作的对象,但不明确具体的操作方法 print('123'.__len__()) ...

  8. 面向对象封装继承多态五大基本原则魔法方法反射

    目录 面向对象 三大基本特征 五大基本原则 魔法方法 反射 面向对象 什么是面向对象 使用模板的思想,将世界万事万物使用对象来表示一个类型 面向对象和面向过程的区别: 面向对象的不就是使用程序处理事情 ...

  9. python3:面向对象(多态和继承、方法重载及模块)

    1.多态 同一个方法在不同的类中最终呈现出不同的效果,即为多态. class Triangle:def __init__(self,width,height):self.width = widthse ...

  10. Java笔记013-IDEA、包、访问修饰符、封装、继承、多态、Super、方法重写/覆盖(override)、java的动态绑定机制

    目录 面向对象编程(中级部分) IDE(集成开发环境)-IDEA IDEA介绍 IDE(集成开发环境)-Eclipse Eclipse介绍 IDEA的安装 IDEA的基本介绍和使用 创建一个java项 ...

最新文章

  1. 前端优秀博客网站收集
  2. 算法竞赛入门经典(第二版) | 程序3-6 WERTYU (UVa 10082)(常量数组)
  3. 《程序是怎样跑起来的》第一章有感
  4. Linux C语言实现清除文件中的内容
  5. 奥威软件大数据bi_商业智能BI软件就是数据可视化工具吗?
  6. win7电脑桌面壁纸曝光过高影响图标怎么办?亲测实用解决方法
  7. oc55--ARC单个对象的内存管理
  8. 【数学建模】python建模专用数据清洗代码(本人实践)
  9. 董小刚先生担任BCF新闻理事
  10. postman获取返回值及tests[]用法
  11. 解决 SQLite报错:OperationalError: row value misused
  12. 如何制作商场超市地摊清仓大甩卖广告语录音
  13. 导图解房(01)黄金圈法则解读 买房这件事儿
  14. python的return详解。
  15. 手机编程python可以实现吗?有哪些软件值得推荐?
  16. UDT协议-基于UDP的可靠数据传输协议
  17. MYSQL语句大全(SQL 高级教程)【下】
  18. python sys.getsizeof 变量的大小
  19. 201612-3-炉石传说
  20. 【全套完结】信号与线性系统分析--Matlab实验报告手册【建议保存】

热门文章

  1. 黑客攻击「宝贝回家寻子网」致数据丢失:丧尽天良
  2. 【名额有限】腾讯技术工程-运维技术沙龙
  3. 能留住女友的,都是王者
  4. Linux文本编辑器-vi/vim
  5. Codeforces Round #159 (Div. 2)
  6. T-Sql - 数据分租求最大指定字段最大的记录
  7. HDU 3065 病毒侵袭持续中(AC自动机 模板)题解
  8. App Icon 和 LaunchImage 尺寸
  9. FineUI.Grid内容换行处理
  10. 最土团购程序一些常见的数据库操作