java中多态性与动态绑定
2015-10-02 00:52
651 查看
一.多态的基本概念
多态性是面向对象的三大特性(封装、继承、多态)之一,多态可以理解为事物存在的多种体现形态,比如动物类(Animal)中有猫类(Cat)、狗类(Dog),一只小猫可以称之为猫,也可以称之为小动物,所以创建对象时可以如下:
Cat x = new Cat();
Animal x = new Cat();
第二种创建方式便是多态的体现形式,即父类的引用指向了自己的子类对象
对象多态性:指的是父类对象和子类对象之间的转型操作
向上转型(自动完成):父类名称 父类对象 = 子类实例 例如:Animal x = new Cat();
Cat eat xx
这里的执行过程是:首先检查父类中是否有eat()方法,如果没有,编译错误;如果有,则检查子类是否覆写了此方法。如果覆写了,则调用子类的eat()方法;如果没有覆写,则调用父类Animal中的eat()方法,后面会详细讲述动态绑定的过程
Animal eat xx
向下转型(强制完成):子类名称 子类对象 = (子类名称) 父类实例 例如:Cat c = (Cat) x;其中x为Animal实例,可见要完成向下转型,必须要有向上转型过程
这里的执行与普通的继承执行一样 ,要注意的是不能将 Animal x转型为Dog类型,因为它指向的是Cat实例
二.多态的前提
多态存在三个必要条件:
1.要么有继承,要么有实现
2.必须要覆写
3.必须要有向上转型过程,即父类引用指向子类对象,不然向下转型不知道将父类对象转成哪一种子类对象
这三点必须要记住!
三.动态绑定(参考Java核心技术卷一)
java当中的向上转型或者说多态是借助于动态绑定实现的,所以理解了动态绑定,也就搞定了向上转型和多态。
绑定指的是一个方法的调用与方法所在的类(方法主体)关联起来,java中private方法,final方法,static方法或者构造器都是静态绑定实现的
静态绑定:在程序执行前已经绑定,由编译器或其他连接程序实现
动态绑定是指在执行期间(非编译期)判断所引用对象的实际类型,根据其实际的类型调用其相应的方法。
下面是调用对象方法的具体执行过程:
运行结果:
吃啥?:mouse
1.编译器查看对象的声明类型和方法名
假设我们调用x.f(param),且x声明为C类的对象,则编译器会例举出所有C类中的f的方法和父类、类中public修饰名为f的方法(父类的private方法不能访问)
2.编译器查看调用方法时提供的参数类型
如果在所有名为f的方法中存在一个与提供参数类型完全匹配的方法,就选择这个方法,这个过程叫做重载解析。例如,调用x.f("Hello")就会选择f(String)而不是f(int),如果没有找到与参数类型匹配的方法,或者发现经过类型转换后(int 可以转换成double,cat可以转换成animal)有多个方法与之匹配,则编译器报错
3.当程序运行,并且采用动态绑定调用方法时,虚拟机一定调用与x所引用对象的实际类型最合适的那个类的方法。
假设x的实际类型是D,它的父类是C,如果D类定义了f(String)那么该方法被调用(前提是父类有f(String)方法),否则就在D的父类中搜寻方法f(String),依次类推。这里D类是Cat类,C类是Animal类
总结:向上转型调用:
1.使用父类类型的引用指向子类的对象
2.该引用只能调用父类中定义的方法和变量
3.如果父类不存在此方法,则编译错误
4.子类存在此方法,且子类覆写了该方法,调用子类的这个方法(动态绑定)
5.子类不存在此方法,调用父类,依次类推
四.多态的例子
这个例子来源于http://www.cnblogs.com/jack204/archive/2012/10/29/2745150.html,我觉得多态理解很有帮助
运行结果:
A and A
A and A
A and D
B and A
B and A
A and D
B and B
B and B
A and D
这里只对第四个输出做个说明:
实例对象为A,参数为B,本应执行A.class中show(A obj)(注意B是A的子类,所以可以看成A类)但是,B.class重写了show(A obj),所以执行B.class show(A obj)
这个过程其实就是动态绑定的实例,具体执行过程如下图:
参考资料: http://www.cnblogs.com/mengdd/archive/2012/12/25/2832288.html http://www.cnblogs.com/jack204/archive/2012/10/29/2745150.html http://blog.sina.com.cn/s/blog_600046120100wdza.html
多态性是面向对象的三大特性(封装、继承、多态)之一,多态可以理解为事物存在的多种体现形态,比如动物类(Animal)中有猫类(Cat)、狗类(Dog),一只小猫可以称之为猫,也可以称之为小动物,所以创建对象时可以如下:
Cat x = new Cat();
Animal x = new Cat();
第二种创建方式便是多态的体现形式,即父类的引用指向了自己的子类对象
对象多态性:指的是父类对象和子类对象之间的转型操作
向上转型(自动完成):父类名称 父类对象 = 子类实例 例如:Animal x = new Cat();
class Animal{ //Animal类,父类 public void eat(){ System.out.println("Animal eat xx"); } } class Cat extends Animal{ //Cat类,子类 public void eat(){ System.out.println("Cat eat xx"); } public void sleep(){ } } public class PolymorphismDemo{ public static void main(String[] args){ Animal x = new Cat();//向上转型 x.eat(); } }运行结果:
Cat eat xx
这里的执行过程是:首先检查父类中是否有eat()方法,如果没有,编译错误;如果有,则检查子类是否覆写了此方法。如果覆写了,则调用子类的eat()方法;如果没有覆写,则调用父类Animal中的eat()方法,后面会详细讲述动态绑定的过程
class Animal{ //Animal类,父类 public void eat(){ System.out.println("Animal eat xx"); } } class Cat extends Animal{ //Cat类,子类 public void eat(){ System.out.println("Cat eat xx"); } public void sleep(){ } } public class PolymorphismDemo{ public static void main(String[] args){ Animal x = new Cat(); //向上转型 x.eat(); } }运行结果:
Animal eat xx
向下转型(强制完成):子类名称 子类对象 = (子类名称) 父类实例 例如:Cat c = (Cat) x;其中x为Animal实例,可见要完成向下转型,必须要有向上转型过程
class Animal{ //Animal类,父类 public void eat(){ System.out.println("Animal eat xx"); } public void sing(){ System.out.println("Animal sing xx"); } } class Cat extends Animal{ //Cat类,子类 public void eat(){ System.out.println("Cat eat xx"); } public void sleep(){ } } public class PolymorphismDemo{ public static void main(String[] args){ Animal x = new Cat(); //向下转型 Cat c = (Cat) x; //向下转型只能转向父类引用指向对象类型 c.eat(); c.sing(); } }
这里的执行与普通的继承执行一样 ,要注意的是不能将 Animal x转型为Dog类型,因为它指向的是Cat实例
二.多态的前提
多态存在三个必要条件:
1.要么有继承,要么有实现
2.必须要覆写
3.必须要有向上转型过程,即父类引用指向子类对象,不然向下转型不知道将父类对象转成哪一种子类对象
这三点必须要记住!
三.动态绑定(参考Java核心技术卷一)
java当中的向上转型或者说多态是借助于动态绑定实现的,所以理解了动态绑定,也就搞定了向上转型和多态。
绑定指的是一个方法的调用与方法所在的类(方法主体)关联起来,java中private方法,final方法,static方法或者构造器都是静态绑定实现的
静态绑定:在程序执行前已经绑定,由编译器或其他连接程序实现
动态绑定是指在执行期间(非编译期)判断所引用对象的实际类型,根据其实际的类型调用其相应的方法。
下面是调用对象方法的具体执行过程:
class Animal{ //Animal类,父类 public void eat(String name){ System.out.println("Animal eat xx"); } } class Cat extends Animal{ //Cat类,子类 public void eat(String name){ //吃啥 System.out.println("吃啥?:"+name); } public void eat(int num){ //吃的数量 System.out.println("吃几只老鼠?:"+num); } public void sing(){ System.out.println("唱歌"); } } public class PolymorphismDemo{ public static void main(String[] args){ Animal x = new Cat(); //向上转型 x.eat("mouse"); } }
运行结果:
吃啥?:mouse
1.编译器查看对象的声明类型和方法名
假设我们调用x.f(param),且x声明为C类的对象,则编译器会例举出所有C类中的f的方法和父类、类中public修饰名为f的方法(父类的private方法不能访问)
2.编译器查看调用方法时提供的参数类型
如果在所有名为f的方法中存在一个与提供参数类型完全匹配的方法,就选择这个方法,这个过程叫做重载解析。例如,调用x.f("Hello")就会选择f(String)而不是f(int),如果没有找到与参数类型匹配的方法,或者发现经过类型转换后(int 可以转换成double,cat可以转换成animal)有多个方法与之匹配,则编译器报错
3.当程序运行,并且采用动态绑定调用方法时,虚拟机一定调用与x所引用对象的实际类型最合适的那个类的方法。
假设x的实际类型是D,它的父类是C,如果D类定义了f(String)那么该方法被调用(前提是父类有f(String)方法),否则就在D的父类中搜寻方法f(String),依次类推。这里D类是Cat类,C类是Animal类
总结:向上转型调用:
1.使用父类类型的引用指向子类的对象
2.该引用只能调用父类中定义的方法和变量
3.如果父类不存在此方法,则编译错误
4.子类存在此方法,且子类覆写了该方法,调用子类的这个方法(动态绑定)
5.子类不存在此方法,调用父类,依次类推
四.多态的例子
这个例子来源于http://www.cnblogs.com/jack204/archive/2012/10/29/2745150.html,我觉得多态理解很有帮助
class A { public String show(D obj) { return ("A and D"); } public String show(A obj) { return ("A and A"); } } class B extends A { public String show(B obj) { return ("B and B"); } public String show(A obj) { return ("B and A"); } } class C extends B { } class D extends B { } public class PolymorphismDemo { public static void main(String[] args) { A a1 = new A(); A a2 = new B(); B b = new B(); C c = new C(); D d = new D(); System.out.println(a1.show(b)); System.out.println(a1.show(c)); System.out.println(a1.show(d)); System.out.println(a2.show(b)); System.out.println(a2.show(c)); System.out.println(a2.show(d)); System.out.println(b.show(b)); System.out.println(b.show(c)); System.out.println(b.show(d)); } }
运行结果:
A and A
A and A
A and D
B and A
B and A
A and D
B and B
B and B
A and D
这里只对第四个输出做个说明:
实例对象为A,参数为B,本应执行A.class中show(A obj)(注意B是A的子类,所以可以看成A类)但是,B.class重写了show(A obj),所以执行B.class show(A obj)
这个过程其实就是动态绑定的实例,具体执行过程如下图:
参考资料: http://www.cnblogs.com/mengdd/archive/2012/12/25/2832288.html http://www.cnblogs.com/jack204/archive/2012/10/29/2745150.html http://blog.sina.com.cn/s/blog_600046120100wdza.html
相关文章推荐
- Python动态类型的学习---引用的理解
- 土人系列AS入门教程 -- 对象篇
- C#托管堆对象实例包含内容分析
- Lua编程示例(二):面向对象、metatable对表进行扩展
- C#与.net高级编程 C#的多态介绍
- C#中面向对象编程机制之多态学习笔记
- C#实现获取不同对象中名称相同属性的方法
- 浅谈Lua的面向对象特性
- Lua面向对象之类和继承浅析
- javascript asp教程第十一课--Application 对象
- JavaScript面向对象的两种书写方法以及差别
- 浅谈c# 面向对象之类与对象
- C#中的多态深入理解
- C#面向对象特征的具体实现及作用详解
- PowerShell中使用Out-String命令把对象转换成字符串输出的例子
- C# 面向对象的基本原则
- C#中多态、重载、重写区别分析
- VBS教程:对象-正则表达式(RegExp)对象
- 设计引导--一个鸭子游戏引发的设计理念(多态,继承,抽象,接口,策略者模式)
- Python回顾与整理2:Python对象