压倒一切的麻烦

时间:2011-10-06 00:54:02

标签: java methods method-overriding

我的代码看起来有点像这样,但这是一个简化版本:

A类:

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

B级:

public class B extends A{
    public void testArgs(B a){
        System.out.println("B");
    }
    public void test(){
        System.out.println("B");
    }
}

班级主要:

public class Main{
    public static void main(String[] args){
        a(new B()).testArgs(new B()); // prints A
        (new B()).testArgs(new B());  // prints B
        a(new B()).test();            // prints B
    }
    public static A a(B b){
        return b;
    }
}

为什么a(new B()).testArgs(new B())打印A而不是B? 是否有某种方法来解决/修复此问题?

编辑:
澄清:

我真正想要的是使用A调用时运行的超类方法,以及使用B调用testArgs时要运行的子类方法。

Casting也不是一个选项,因为在实际代码中,与此不同,我不知道方法调用的结果是否实际上是B。

编辑:
解决方案:

感谢大家的回答。感谢有关覆盖的澄清。我用它来实现所需的行为 对于将来遇到类似问题的人:
将B类改为

public class B extends A{
    public void testArgs(A a){       // Corrected overriding, thanks
        if(a instanceof B)           // Check if it is an instance of B
            System.out.println("B"); // Do whatever
        else                         // Otherwise
            super.testArgs(a);       // Call superclass method
    }
    public void test(){
        System.out.println("B");
    }
}

4 个答案:

答案 0 :(得分:6)

两个testArgs函数不同。一个需要A,另一个需要B。因此,B版本不会覆盖A版本。由于a(new B())类型为AB扩展为A,因此将运行A版本。

有一个“解决方法”:

public class B extends A{
public void testArgs(A a){ // <-- note how this is A a, not B a 
    System.out.println("B");
}
public void test(){
    System.out.println("B");
}
}

然后,您会看到所有3个案例B(因为B的{​​{1}}会覆盖testArgs的{​​{1}}}

答案 1 :(得分:1)

调用a(new B())返回类型B的新A实例,调用testArgs()时,它会在类A中调用并打印"A" }。正确。

如果方法testArgs()覆盖超类中的那个,那么子类版本将通过多态来调用(但不是你的情况)。

因此,要获得预期结果,类B需要在super:

中正确覆盖该方法
public class B extends A{
public void testArgs(A a){ // polymorphism would work 
   System.out.println("B");
} 
...

答案 2 :(得分:0)

在运行时调试问题相当困难。有一种非常简单的方法可以让编译器通过使用anotation @Overrides

来警告你

公共类B扩展A {

@Overrides
public void testArgs(B a){
    System.out.println("B");
}

@Overrides
public void test(){
    System.out.println("B");
}

}

如果我无意中遗漏了某个参数或使用了错误的参数,那么@Overrides将在编译时捕获我的错误。

答案 3 :(得分:-2)

在您打印“A”的第一个声明中,您可以通过将静态a()调用的结果转换为B来解决此问题:

((B) a(new B())).testArgs(new B());