在前面一篇文章中,我已经介绍了关于java多态中重载的理解与规则
所以这篇文章主要介绍多态中的覆盖机制。
首先重载与覆盖除了表现方式不同之外,还有运行时间上的不同,重载是在编译期间就已经可以确定好调用的方法,而覆盖则是在运行期间才能确定。(这是由于覆盖是一般是建立在继承之上的,即需要通过继承链(指针)的查找)
多态覆盖的主要难度表现在:
对于一个父类变量,引用的是子类对象,那么需要知道父类变量在调用方法时,调用的是谁的方法。
一、实例方法在运行多态时的表现
这是父类方法
public class Forefather { public void normal() { System.out.println("这是父类的普通方法"); } }
这是子类方法
public class Inheritor extends Forefather{ public void normal() {//这里覆盖了父类的同名方法 System.out.println("这是子类的普通方法"); } }
多态表现
public class ShowStrange { public static void main(String args[]) { Forefather pfather;//定义一个父类变量 Inheritor pson;//定义一个子类变量 pfather = new Inheritor();//创建子类对象 pfather.normal();//调用子类方法 // pson = new Forefather();子类的变量不能创建父类对象 pson = new Inheritor(); pson.normal(); } }
运行结果是:
这是子类的普通方法
这是子类的普通方法
这就说明该变量是什么对象时,就调用什么方法,而与声明变量的类无关。
但是更神奇的在这里:
public class Ancestors {//父类变量 public void common() { System.out.println("这是父类的common方法"); } public void anceshow() { common(); } }
public class Derive extends Ancestors{//子类变量 public void common() {//覆盖父类的同名方法 System.out.println("这是子类的common方法"); } public void deriveShow() { anceshow(); } public static void main(String args[]) { Ancestors oa = new Ancestors(); oa.anceshow();//执行的是父类的方法 Derive ob = new Derive(); ob.deriveShow();//执行的是子类的方法 } }
运行结果:
这是父类的common方法
这是子类的common方法
神奇之处就在于ob.deriveshow执行是调用的父类的anceshow方法,而在执行anceshow方法时并未调用父类的common方法,而是返回到子类中执行子类的common方法,相当于自己出去了一圈又找回来了
补充:
讨论完方法后,你是否对于成员变量是否也具有多态性有疑问?
这里就不补充源代码了,明确的说,对于成员变量而言无论是实例,静态成员,都没有这一特性,对成员变量的引用在编译时就已经确定好了,即声明的变量为那个类,这个成员变量就属于哪个类。