对于问题的第一部分,我认为维基百科提供了一个很好的定义:
在面向对象的程序设计中,子类型多态或包含多态是类型理论中的一个概念,其中名称可以表示许多不同类的实例,只要它们与某个公共超类相关即可。包含多态性通常通过子类型化来支持,即,不同类型的对象可以完全替代另一种类型(其基本类型)的对象,因此可以通过公共接口进行处理。或者,可以通过类型强制(也称为类型转换)来实现包含多态性。
面向对象编程中的另一种称为多态性的 Wikipedia术语似乎很好地回答了您的问题。本文中的第二篇参考文章“
了解类型,数据抽象和多态性”也详细介绍了此问题。
Java中的这种子类型化功能是通过继承类和接口来实现的。尽管从继承的角度来看,Java的子类型功能可能并不总是很明显。以与泛型的协方差和逆方差为例。而且,数组在序列层次结构中的任何地方都不明显,但它们是可序列化和可克隆的。也可以说,通过原始扩展转换,Java中的数字类型也是多态的。并且运算符的行为取决于其 *** 作数。
无论如何,继承在某些这种多态性的实现中起着重要作用。
重载与覆盖
问题的第二部分似乎是关于选择给定方法的实现。显然,如果一个类重写了一个方法,并且您创建了该类的实例,则即使要通过父类的引用访问该对象,也要调用该方法的重写版本。
正如您所指出的那样, 正确 选择方法的 实现
是在运行时完成的,现在,要调用的方法的签名是在编译时确定的。由于重载是关于具有相同名称和不同签名的不同方法的,所以这就是为什么重写方法选择发生在编译时的原因。
编译时的覆盖方法选择
第15.12节“
方法调用表达式
”中的Java语言规范(JLS)详细解释了编译器遵循的过程,以选择正确的方法进行调用。
在那里,您会注意到这是一个 编译时 任务。JLS在15.12.2小节中说:
此步骤使用 方法 的 名称 和 参数表达式的类型
来定位可访问和适用的方法。可能有不止一种这样的方法,在这种情况下,选择了最具体的方法。
要验证其编译时性质,可以执行以下测试。
声明一个这样的类并进行编译。
public class ChooseMethod { public void doSomething(Number n){ System.out.println("Number"); }}
声明第二个类,该类调用第一个类的方法并进行编译。
public class MethodChooser { public static void main(String[] args) { ChooseMethod m = new ChooseMethod(); m.doSomething(10); }}
如果您调用main,输出将显示
Number。
现在,向该类中添加第二个更具体的 重载 方法
ChooseMethod,然后重新编译它(但不要重新编译另一个类)。
public void doSomething(Integer i) { System.out.println("Integer");}
如果再次运行main,则输出仍为
Number。
基本上是因为它是在编译时决定的。如果您重新编译
MethodChooser该类(带有主类的类),然后再次运行该程序,则输出将为
Integer。
因此,如果要强制选择重载方法之一,则参数的类型必须在编译时且不仅在运行时与参数的类型相对应。
在运行时覆盖方法选择
同样,方法的签名是在编译时确定的,而实际的实现是在运行时确定的。
声明一个这样的类并进行编译。
public class ChooseMethodA { public void doSomething(Number n){ System.out.println("Number A"); }}
然后声明第二个扩展类并进行编译:
public class ChooseMethodB extends ChooseMethodA { }
在MethodChooser类中,您可以执行以下 *** 作:
public class MethodChooser { public static void main(String[] args) { ChooseMethodA m = new ChooseMethodB(); m.doSomething(10); }}
如果您运行它,则会得到输出
NumberA,这很好,因为该方法尚未被覆盖
ChooseMethodB,因此调用的实现是的实现
ChooseMethodA。
现在,在中添加重写的方法
MethodChooserB:
public void doSomething(Number n){ System.out.println("Number B");}
并重新编译该代码,然后再次运行main方法。
现在,您得到了输出
Number B
这样,实现是在运行时选择的,不需要重新编译
MethodChooser该类。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)