示例:
猫和狗都继承了动物类,并且重写了eat方法,创建对象的时候,子类的类型提升为父类的引用:method(new Cat()) 这就是父类的引用指向子类的对象
多态的弊端:
如上图所示,这样只能调用子类和父类都有的方法,不能调用子类特有的方法 例如Cat类里的catchMouse是不能这样调用的
如果想调用,要强制类型转换,将对象转换成子类的类型,就可以调用了,如下图所示:将对象a强制转换成Cat类型
下面看一下多态中非静态方法的特点:
再来一个多态原理图
如上图所示
1、为main方法开辟栈帧、父类和子类进入方法区
2、执行main中Person p = new SuperMan():在堆中开辟一块内存给SuperMan,其中有一块是super 存放从父类继承来的东西,还有this指向这块内存,将super这块内存的地址存入栈中p里面,p只能指向从父类继承来的那块内存,不能指向SuperMan的全部内存
3、执行p.谈生意():编译的时候找到方法区中Person里的谈生意,运行的时候查看到子类重写了这个方法,就调用子类的谈生意方法,这就是多态,是动态绑定
4、SuperMan sm = SuperMan(p):此时在栈帧中加入sm,里面地址指向堆中的superman这块完整的内存,然后sm调用方法区中的fly方法
下面看一下多态中成员变量的特点:
这里调用p.num输出的是10,因为对象p只能看到child内存中super这块存放父类的内存,所以输出的是父类的num
下面看一下多态中静态方法的特点:
如上图所示,p.print()和Parent.print()这两种调用方法都是输出Parent ,都是找父类
被静态修饰,就不存在动态绑定