2010-01-28 2 views
5

Я новичок в Java, и я прочитал несколько руководств по переопределяющим методам, но пример, на который я смотрю, не работает так, как я ожидаю. Например, у меня есть код:Переопределение метода 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(), который я изначально не показывал (извините). Я предполагаю, что мне нужно сделать «новый A(). Run();» более общий для использования имени текущего класса. Это возможно?

+5

Как вы создаете и называете это? –

+1

@Prasoon Не было упоминания файла, только классов. Мы не могли сделать вывод о фактических файлах, в которых они находились. – KLE

ответ

6

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

(new B()).run(); 

Какой бы ни была проблема есть, это не в коде, который вы указали.

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

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

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

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

+0

Стыдно, что Java не раскрывает текущий класс, в котором находится код. Я больше знаком с Python, где я мог бы делать тип (self) или явно определять main() как classmethod. В любом случае, я закончил тем, что просто дал B свой собственный main(), который напрямую запускает B, и это устраняет проблему. – Cerin

+0

@Chris: проблема не в том, что Java не раскрывает ее (она есть; внутри метода экземпляра 'this.getClass()' дает вам экземпляр класса, который сообщает вам все, что вам нужно знать о классе , если вы находитесь в классе (статическом) методе, вы уже знаете, в каком классе вы находитесь, и можете использовать имя - например, 'A' - напрямую, чтобы получить экземпляр класса. Это не проблема, с которой вы сталкиваетесь. Проблема, с которой вы сталкиваетесь, заключается в том, что 'B' просто не участвует в какой-либо форме или форме, когда вызывается' A.main'. 'B' тоже не может быть. Это не язык, это то, что вы пытаетесь сделать. :-) –

+0

@ T.J. Crowder: Исправлено, но только потому, что в Java у меня нет выбора, кроме жесткого кода «new A()». В Python main() может быть классом, первый аргумент которого будет автоматически «cls», поэтому я мог бы создать экземпляр класса, просто выполнив «cls()». Это было бы наследуемым, поэтому мне не пришлось бы писать отдельный main() для B. – Cerin

3

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

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

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

A a = new B(); 
a.run(); 
+1

'A a = new B()' также должен работать отлично (если только методы не являются статическими). – Nate

+0

@Bedwyr Выход такой же! :-) – KLE

1

Это зависит от создания экземпляра. Попробуйте следующее:

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

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

B v3 = новый A(); не будет компилироваться, это невозможно! – KLE

+0

Это приведет к ошибке компиляции в строке 3. A не относится к типу B. –

+0

Да, я знаю это, но этот результат полезен. – demas

2

Работы для меня.

Вот мой код для 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

Я попробовал ваш пример, и мой результат был 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

Если внешняя программа конкретизирует А, вы будете иметь, а не Б.

Но вы можете попробовать что-то вроде этого, используя некоторые размышления, и передать «com.mypackage.A» или «ком .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(); 

} 
Смежные вопросы