Основная проблема - PullRequest
       8

Основная проблема

6 голосов
/ 06 октября 2011

Мой код выглядит примерно так, но это упрощенная версия:

класс 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");
    }
}

класс Main:

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, и метод подкласса, запускаемый при вызове testArgs с B.

Приведение также не является вариантом, потому что в реальном коде, в отличие от этого, я не знаю, является ли результат вызова метода на самом деле 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 ]

6 голосов
/ 06 октября 2011

Две функции testArgs различны. Один берет A, а другой - B. Таким образом, версия B не переопределяет версию A. Поскольку a(new B()) имеет тип A и B расширяет 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");
}
}

Тогда вы увидите B для всех 3 случаев (потому что B testArgs переопределит A 'testArgs)

1 голос
/ 06 октября 2011

Вызов 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");
} 
...
0 голосов
/ 06 октября 2011

Отладка проблемы во время выполнения довольно сложна. Существует очень простой способ предупредить вас компилятором с помощью аннотации @ Overrides

открытый класс B расширяет A {

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

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

}

Если я случайно пропустил параметр или использовал неправильный, то @Overrides поймает мою ошибку во время компиляции.

0 голосов
/ 06 октября 2011

В своем первом утверждении, которое печатает «A», вы можете обойти проблему, приведя результат статического a() вызова к B:

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