了解Java继承

了解Java继承

问题描述:

考虑下面的Java代码:了解Java继承

class mainul { 

    public static void main(String[] args) { 

    /*block 1*/ 
     B b1 = new B(); 
     A a1 = b1; 
     a1.m1(b1); 

    /*block 2*/ 
     B b2 = new B(); 
     B a2 = b2; 
     b2.m1(a2); 
    } 
} 

class A { 

    public static void p(Object o) { 
     System.out.println(o.toString()); 
    } 

    public void m1(A a) { 
     p("m1(A) in A"); 

    } 
} 

class B extends A { 

    public void m1(B b) { 
     p("m1(B) in B"); 
    } 
} 

有人能提供一些线索,为什么这个程序的输出是

m1(A) in A 
m1(B) in B 

人们期望块1的输出为“因为a1的动态类型是B的事实,我注意到A和B中m1的函数签名不匹配(一个需要一个A类型的对象,另一个需要B的另一个作为它的参数)和A中的方法似乎得到优先权,但不能真正将它与我的输出链接,因为它似乎与th不一致块2的输出。

感谢您的时间

正如你注意到,B.m1(B)不会覆盖A.m1(A),因为他们采取不同的参数(尝试添加@Override注解,你会看到编译器抱怨)。所以它永远不能通过对A的引用来调用。

但是,它可以通过参考B来调用。

+0

的确,让它期待一个A实例,它就会起作用。 – MarioDS 2012-04-10 21:18:01

这两个方法签名与Oli说的不同。

当你在这里叫他们每个人:

B b1 = new B(); 
    A a1 = b1; 
    a1.m1(b1); 

    /*block 2*/ 
    B b2 = new B(); 
    B a2 = b2; 
    b2.m1(a2); 

您先通过类型A的对象,然后通过B型的对象,它是所有Java在这方面关注的是,它不关心你做了什么对象,就是它是什么。

+0

另外,按照您设置的方式,您是否打算为每个对象都有一个'toString'方法,然后将该对象传递给您的'p(Object o)'方法 – 2012-04-10 21:22:38

被调用的方法是在编译时设置的(在这种情况下是A.m1(A))。我知道你认为这是动态的吗?动态绑定是运行时绑定。嗯,是的,但它只对A.m1(A)的方法是动态的。因此,A的任何子类都可以提供一个替代实现,但其签名必须相同,否则就是重载方法,这与方法不同。

这也意味着呼叫中使用的参数没有考虑到动态绑定。方法名称和正式签名是在编译时设置的。改变类型,它不是相同的方法,不会被调用。

你可以做到这一点,以强制编译器看到的方法:

a1.m1((A)b1) 

这告诉哪种方法你尝试调用编译器。

只需按照代码:

块1

B b1 = new B(); //- variable b1 (type is B) points to instance of B() 

A a1 = b1;  //- variable a1 (type is A) points to instance of B() .. same as b1 is 
        // pointing to. 

a1.m1(b1);  // Call Method m1 on a1 (i.e. of class A) ..IMP catch > as a1 holds 
        // object of b1, if there is method in Class A which is overriden in B, 
        // call that overriden method. But here method m1() is not overriden 
        // by B it will call method of class A. 

块2

B b2 = new B(); // variable b2 (type B) points to instance of B() 

B a2 = b2;  // variable a2 (type B) points to same instance as b2 is pointing to. 

b2.m1(a2);  // call method m1 of b2 (of class B). There is only one method m1 in b2 
       // and b2 holds object of B, it must call method of class B 

另外,如果你想让块1成为“B中的m1(B)”,只需将类A中的方法标记为虚拟,并在类B中覆盖相同。