2016-02-15 53 views
0
public class A { 

    public void m1(A a) { 
     System.out.println("m1(A) in A"); 
    } 

    public void m4() { 
     System.out.println("m4() in A"); 
    } 
} 

public class B extends A{ 

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

    public void m4() { 
     System.out.println("m4() in B"); 
    } 

} 

public class Test { 

    public static void main(String[] args) { 

     B b = new B(); 
     A a = b; 
     a.m1(b); // returns m1(A) in A 
     a.m4(); // returns m4() in B 
    } 

} 

有人能解释为什么a.m1(b)使用A的方法,而a.m4()使用B的方法吗?在java中动态绑定方法 - 为什么这个方法?

我特别不明白这个变量(a)是如何调用两个不同类的方法的。我认为,在运行时,a要么视为A或B,然后应导致从A两种方法或B.

回答

1

让我们从对象声明的基础入手。

让我们考虑一个类Animal

Animal anim=new Animal(); 

Anim anim告诉JVM建立类型动物的新的参考变量和new Animal()询问JVM以创建新的Animal对象。这两个语句结合=告诉JVM创建一个Animal类型的引用变量,并为它分配一个动物对象。

什么是anim

  • anim类似于控制Animal类型的对象的行为的遥控器。我们用它来指代对象。

我希望现在清楚。

现在让我们继续继承和多态。考虑一个新的类Dog,它延伸AnimalDog成为Animal的子类。

如果继承,您可以考虑IS A规则。在这种情况下,由于Dog已延长Animal,Dog IS A Animal。我希望你得到了我。这是多态性进入图片的地方。多态性意味着您可以实际使用超级类引用变量来引用子类对象。

Animal anim1=new Dog(); 

我们已经创建了一个遥控anim1其控制Dog对象。这个anim1参考(遥控器)只能控制AnimalDog的具体方法。这个遥控器还可以控制过度使用的方法,但不能控制Dog中没有继承或覆盖的任何新方法。

现在,让我们继续前往您的课程ABB IS-A A,因为它扩展了A

这意味着A a= new B();是多态的。这是类似于YOH已经使用下面的代码完成:

B b=new B(); 
A a=b; 

现在为什么a.m1(b);转到方法在Aa.m4();B

让我们其他人去之前看的东西:

你有A类的方法: public void m1(A a)

你有B类的方法: public void m1(B b)

重写意味着你实际上在子类中重新定义了一个继承的方法。所以在你的情况下,m1(B b)B类没有超越,因为它具有不同的paraneter。它具有的参数类型为B,而原始m1(A a)A中查找类型为A的参数。简而言之,您的类B有两种方法,分别命名为m1。 从A继承的一个和参数类型为B的新方法或过载方法。

就像我已经提到的,我们的遥控器a只能看到类A特定的方法。它看不到过载的方法。这就是原因,它实际上是继承了方法m1(A a)

现在,a.m4();转到m4()B。为什么?

  • 因为在Bm4()是过深重的方法和a可以看到它。

假如你叫b.m1(b),将被用于B方法。

总结: 您可以使用超级引用变量/ remote来引用/指向子类对象,但此远程只能看到继承的方法,包括过度使用但未超载。 但是,子类型的引用将能够看到所有的方法。

为了帮助您识别过度缠身和重载的方法:

过缠身的方法是这样的:

  • 参数必须是相同的,参数必须相同或兼容。
  • 方法不能少访问。那就是public不能做成private

重载的方法,如:

  • 返回类型可以是不同的。

  • 参数类型或参数的数量应该有所不同。

  • 访问级别是可以改变的

使用上面的规则,你可以轻松地idebtify是m1(B b)B实际上是一个重载的方法,因为参数类型从m1(A a)变化。

最后,B拥有3种方法:

  • m1(A a) inherted

  • m1(B b)超载

  • m4()过缠身

请评论,如果您有任何疑问或一个例子错误。

+0

哇。非常感谢你的努力!我的错误是假定m1(B b)是一个覆盖,因为每个B也是一个A.但现在它实际上是有道理的,事实并非如此。很好的答案! – Daniel

+0

我很高兴它帮助你。快乐学习。 –

4

这两种方法那是因为B.m1(B)不会覆盖A.m1(A)。这是一个重载,因为它的参数是不同的类型。

为了覆盖它,您需要将参数类型更改为A

注意,它总是一个好主意,注释你与@Override重写你想方法:那么编译器会告诉你,如果你没有真正覆盖方法。

还要注意的是,如果你叫b.m1(b);呼吁B的方法,因为这是超载更具体的说A.m1(A)。然而,使用当前代码,在编译时可以匹配的唯一方法是A.m1(A),因为众所周知的是aA的一个实例或它的一个子类型:已知可用的唯一方法是方法在A

调用的方法在编译时选择,而不是运行时。

+0

但是为什么a.m4()返回B方法的消息? – Daniel

+0

因为*是重写'A.m4()'。它具有相同的参数(都为零)和相同的返回类型('void')(严格来说,返回类型不需要完全匹配:重写方法的返回类型必须与重写方法的协变)。 –

+0

因此,因为'a'是一个形式A,所以首先看A中的方法。因为B中的方法m1具有与A中的方法不同的参数类型(尽管B中的参数类型实际上更适合) ,选择A中的方法。对于m4(),选择B的方法,因为它覆盖A中的方法,'a'是引擎盖下的B。是对的吗? – Daniel

相关问题