2010-09-20 39 views
0

以下是关于我的疑问的代码snipplet。用Java调度的动态方法

class A { 
    void someMethod(A param) { 
     System.out.println("A"); 
    } 
} 

class C extends A { 
    void someMethod(C param) { 
     System.out.println("C"); 
    } 
} 

class DMD { 
    public static void main(String[] args) { 
     A ac = new C(); 
     C c = new C(); 
     ac.someMethod(c); 
    } 
} 

输出:

A 

但我除外的输出作为

C 

因为我为C分配的内存,和A被参照的C存储器位置,因此,如果我将A引用指向C的方法,并将参数作为传递类型,那么我期望someMethod(C)方法应该执行。

任何人都可以请给我这种行为的正当理由吗?

在此先感谢。

+8

你有什么不能编译,因为C不扩展A. – 2010-09-20 14:35:35

+0

这与正则表达式无关btw – sepp2k 2010-09-20 14:40:15

+1

http://stackoverflow.com/questions/321864重复(如果你调整编码错误)/java的动态绑定 - 方法-首要/ 322234#322234 – Robin 2010-09-20 14:58:27

回答

2

决定使用哪种方法基本上有两个阶段:首先是重载决议,然后是方法派遣。重载解析发生在编译时,在运行时分派方法。

在这个例子中重载解析决定该过载someMethod(A param)应该使用,因为这是的someMethodA类中定义的唯一的过载(和静态类型的acA)。

在运行时,它决定使用哪一个实现的someMethod(A param),但由于只有一个实现(C.someMethod(C)没有覆盖someMethod(A)CA更具体),A.someMethod(A)选择。

3

在编译时实现方法调用,该方法采用不同的参数类型(重载)。 (这是你的情况下)

如果所有3种方法接受A型的论点 - 即方法覆盖存在,才多态性会发挥作用,将引发提供C方法之间是有继承关系A和C即C延伸A.

0

您写的代码将无法成功编译。你不能说“A ac = new C();”因为C没有扩展A.如果你声称已经运行并得到了输出,你必须从运行代码中错误地复制了一些东西到这篇文章中。

如果出于说明的原因,您的代码真的说“A ac = new A();”,那么您的代码仍然不会运行,因为A.someMethod需要A而不是C。陈述ac.someMethod(c)执行功能A.someMethodac类型为A,因此对ac执行任何功能将从类A获得该名称的功能。试图将C类型的参数传递给声明为A类型的参数的函数不会“切换”您使用来自不同类的函数,该函数使用此类参数。超载只能在一个班级中使用。

也许你在想什么的是一个例子更是这样的:

class A { 
    public void someMethod(A a) { 
     System.out.println("A"); 
    } 

    public void someMethod(B b) { 
     System.out.println("B"); 
    } 
} 

class Dmd { 
    public static void main(String[] args) { 
     A a = new A(); 
     B b = new B(); 
     a.someMethod(b); 
    } 
} 

这将输出“B”。

这里的区别在于类A有两个版本的函数someMethod。其中一个需要A,一个需要B。当我们将其称为B时,我们得到B版本。

你是否看到这与你的例子有何不同?您正在声明三个类,每个类都有一个函数someMethod。在这里,我们有一个类有两个功能,分别命名为someMethod。这在Java中非常不同。