2015-12-09 3 views
3

У меня есть эти классы:Java суперкласс вызывает метод подкласса

class A { 
    public void f() { System.out.println("f() in A"); } 
    public void g() { System.out.println("g() in A"); f(); } 
} 

class B extends A { 
    public void f() { System.out.println("f() in B"); } 
} 

Почему

B b = new B(); 
A a = b; 
a.g(); 

распечатанной

g() in A 
f() in B 

и не

g() in A 
f() in A 

Есть что-то, что мне не хватает?

+0

Читайте о полиморфизма и переопределения метода. – Eran

ответ

2

Да, хотя переменная «a» относится к типу A, ссылка на объект, которую он имеет, имеет тип B, поэтому f() в B - это то, что называется.

1

https://docs.oracle.com/javase/tutorial/java/IandI/polymorphism.html

Это называется полиморфизмом. Это позволяет нам делать такие вещи, как держать список типов Animal, но когда мы помещаем в него кошку и делаем animal.performcall(), он печатает мяу. Это пример, который дал мне мой учитель много лет назад :)

+0

На самом деле это не только полиморфизм, это просто способ получить полиморфное поведение, но есть несколько способов (даже в Java). – Jack

0

Тип ссылочной переменной объекта определяет, какие методы доступны.

Класс объекта определяет, какие существуют методы. Эти методы, которые существуют, но недоступны, могут быть доступны посредством кастинга.

т.е: ((B) a).g(); Позволит вам получить доступ к версии G. Это B работает только потому, что под a является B.

3

Это связано с тем, что Java использует dynamic dispatch по умолчанию (и принудительно) для методов классов.

Эта функция гарантирует, что при вызове метода наиболее специализированная версия будет выбрана. В вашем случае, начиная с B extends A, это означает, что public void f() реализация B более специализирована, чем одна из A. Итак, хотя A a статически имеет тип A, он динамически относится к типу B и этот метод выбран.

0

Теперь у вас есть идея о полиморфизме и переопределении.

Поскольку вы не получить ожидаемый результат, я хотел бы предложить способ получить ожидаемый результат через метод затенение или скрываются

Если вы повторно определить базовый класс нестатического &, не частный метод в производный класс, он называется переопределением.

В этом примере выполняется экземпляр B и, следовательно, f() был вызван из B вместо А.

Если вы повторно определить базовый класс статический метод/переменная производного класса, это называется скрывается или затенение.

В приведенном выше примере просто добавьте static, модифицированный для метода g(), и вы получите требуемый выход. Теперь g() метод

class A { 
    public static int i=10; 
    public static void f() { 
    System.out.println("f() in A:i="+i); 
    } 
    public void g() { System.out.println("g() in A"); f(); } 
} 

class B extends A { 
    public static int i=20; 
    public static void f() { 
     System.out.println("f() in B:i"+i); 
    } 
} 
public class Test2 { 
    public static void main(String args[]){ 
     B b = new B(); 
     A a = b; 
     a.g(); 
    } 
} 

выход:

g() in A 
f() in A:i=10 
Смежные вопросы