2015-05-04 11 views
0
class G { 

    int x = 5; 
} 

class H extends G { 

    int x = 6; 
} 

public class CovariantTest { 

    public G getObject() { 
     System.out.println("g"); 
     return new G(); 
    } 

    public static void main(String[] args) { 
     CovariantTest c1 = new SubCovariantTest(); 
     System.out.println(c1.getObject().x); 
     System.out.println(new H().x); 
    } 
} 

class SubCovariantTest extends CovariantTest { 

    public H getObject() { 
     System.out.println("h"); 
     return new H(); 
    } 
} 

Выход:Java - Перекрытие с общековариантными типами WRT переменных

h 
5 
6 

Видимо два Println заявления в основном методе не то же самое. Как новый объект H() возвращается из метода getObject класса SubCovariant, назначенного для ссылки G?

+2

** Вы никогда не получите * 5 в качестве вывода * с кодом, который вы отправили !! ** –

+0

Похоже, что есть ошибка опечатки. Где-то x должно быть 5 'int x = 5;' – Kartic

+0

thanks..edited to int x = 5; – rpg

ответ

1

G является объявленным типом, H является фактическим типом.

Объявленный тип - это то, что вы можете думать об объекте как, например, G в вашем примере.

Фактический тип - это то, что на самом деле объект, т. Е. H в вашем примере. Это обеспечивает фактическое поведение, включая любые, которые он может наследовать от родительских классов, включая G.

1

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

CovariantTest c1 = new SubCovariantTest(); 

Это преобразует тип ссылки, но не реализацию. если вы должны были сделать

System.out.println(c1.getClass()); 

это печать будет

SubCovariantTest 

поэтому, когда вы звоните getObject() на этом случаях, это не должно удивлять, что это вызывает SubCovariantTest.getObject()


сравнения, static методы не следуют полиморфизму. Они не могут быть переопределены одинаково (они могут быть только скрыты). Если вы должны были сделать getObject() статическим в обоих случаях, вы обнаружите, что c1.getObject() будет вызывать соответствие типа c1, поскольку метод вызова определяется во время компиляции, а не во время выполнения. На самом деле вы можете это сделать.

public class CovariantTest { 

    public G static getObject() { 
     System.out.println("g"); 
     return new G(); 
    } 

    public static void main(String[] args) { 
     CovariantTest c1 = null; 
     System.out.println(c1.getObject().x); // prints "g" "5" 
    } 
} 

class SubCovariantTest extends CovariantTest { 

    public H static getObject() { 
     System.out.println("h"); 
     return new H(); 
    } 
} 

Вы можете получить доступ к null ссылку здесь, потому что он не используется во время выполнения. Компилятор использует только тип ссылки, как вы могли бы ожидать в своем вопросе.

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

  • Нет связанных вопросов^_^