Переопределение метода Java - PullRequest
5 голосов
/ 28 января 2010

Я новичок в Java, и я прочитал некоторые учебники по переопределению методов, но пример, который я смотрю, работает не так, как я ожидаю. Например, у меня есть код:

public class A{
    public void show(){
        System.out.println("A");
    }
    public void run(){
        show();
    }
    public static void main( String[] arg ) {
        new A().run();
    }
}
public class B extends A{
    @Override
    public void show(){
        System.out.println("B");
    }
}

Когда я создаю экземпляр и вызываю B.run (), я ожидаю увидеть вывод "B". Однако вместо этого я вижу «А». Что я делаю не так?

Редактировать: Да, классы находятся в двух отдельных файлах. Они показаны вместе для краткости.

Редактировать: я не уверен, как создается экземпляр B, поскольку это делается сторонней программой, использующей загрузчик классов.

Редактировать: дополнительная информация о сторонней программе. Он начинается с вызова A.main (), который я изначально не показывал (извините). Я предполагаю, что мне нужно сделать "new A (). Run ();" более универсально использовать имя текущего класса. Это возможно?

Ответы [ 6 ]

6 голосов
/ 28 января 2010

Этот код выведет B, если вы:

(new B()).run();

Какая бы ни была проблема, это не в коде, который вы цитировали.

Обновлено (после редактирования)

Если сторонняя программа вызывает A.main(), нет ничего (разумного), что вы можете сделать в B, который внедрит себя в A. Пока A.main делает new A().run(), он будет иметь экземпляр A, а не B. Не нужно использовать «текущее имя класса», или, если оно есть (зависит от вашей точки зрения), это A, а не B.

Вам нужно будет заставить стороннюю программу вызывать B, а не A, или просто изменить A напрямую (например, полностью избавиться от B). Вы не хотите изменить A, чтобы использовать B; это тесно связывает его с потомком и делает разделение между ними в значительной степени бессмысленным.

Надеюсь, это поможет.

3 голосов
/ 28 января 2010

Я попытался поместить ваши два класса в два файла, и это сработало, выдав «B». Я позвонил:

 B b = new B();
 b.run();

ОБНОВЛЕНО: также работает как (потому что это тот же экземпляр времени выполнения):

 A a = new B();
 a.run();
2 голосов
/ 28 января 2010

У меня работает.

Вот мой код для A и B:

package so;

public class A{
    public void show(){
        System.out.println("A");
    }
    public void run(){
        show();
    }
}

class B extends A{
    @Override
    public void show(){
        System.out.println("B");
    }
}

Вот моя точка входа:

package so;

public class EntryPoint {

    public static void main(String[] args) {
        B b = new B();
        b.run();
    }
}

Он печатает 'B'.

1 голос
/ 28 января 2010

Если ваша внешняя программа создает экземпляр A, у вас будет A, а не B.

Но вы можете попробовать что-то вроде этого, используя некоторое отражение, и передать "com.mypackage.A" или "com.mypackage.B" в качестве аргументов вашей программе.

С этим кодом (отсутствует исключение) вы сможете печатать «A» или «B» в зависимости от передаваемого строкового параметра.

public static void main( String[] arg ) {
    String className = arg[0];
    Class myClass  = Class.forName(className);
    Constructor cons = myClass.getConstructor(new Class[0]);
    A myObject = (A) cons.newInstance(new Object[0]);
    myObject.show();

}
1 голос
/ 28 января 2010

Я попробовал ваш пример, и мой вывод был B .

Как дела? Вот точный код, который я запустил.

public class Test {
    public static class A {
        public void show() {
            System.out.println("A");
        }

        public void run() {
            show();
        }
    }

    public static class B extends A {
        @Override
        public void show() {
            System.out.println("B");
        }
    }

    public static void main(String args[]) {
        A a = new B();

        a.run();
    }
}
1 голос
/ 28 января 2010

Это зависит от реализации. Попробуйте это:

 A v1 = new A();
 A v2 = new B();
 B v3 = new A();
 B v4 = new B();

 v1.run()
 v2.run()
 v3.run()
 v4.run()
...