2012-05-23 2 views
31

Я изучаю переопределение функций-членов в JAVA и думал об экспериментировании с переопределяющими переменными-членами.Переопределение переменных элемента в Java

Итак, я определил классы

public class A{ 
    public int intVal = 1; 
    public void identifyClass() 
    { 
     System.out.println("I am class A"); 
    } 
} 

public class B extends A 
{ 
    public int intVal = 2; 
    public void identifyClass() 
    { 
     System.out.println("I am class B"); 
    } 
} 

public class mainClass 
{ 
    public static void main(String [] args) 
    { 
     A a = new A(); 
     B b = new B(); 
     A aRef; 
     aRef = a; 
     System.out.println(aRef.intVal); 
     aRef.identifyClass(); 
     aRef = b; 
     System.out.println(aRef.intVal); 
     aRef.identifyClass(); 
    } 
} 

Выход является:

1 
I am class A 
1 
I am class B 

Я не могу понять, почему, когда Ареф установлен б intVal еще класса А?

+0

возможно дубликат [Плавный путаницы относительно переопределения, где переменные обеспокоены] (http://stackoverflow.com/questions/12589274/slight-confusion-regarding-overriding-where-variables-are-concerned) –

+0

Я думаю, это не тот же вопрос, так как другой смешивает несколько особенностей языка, в то время как этот - чисто переменные, которые не являются полиморфными. –

+0

@Vic Seedoubleyew. Но мне кажется, что это дубликат [этого вопроса] (http: // stackoverflow.com/q/7794621/1303323) –

ответ

41

Переменные не являются полиморфными в Java; они не переопределяют друг друга.

+1

Итак, поскольку переменная не переопределена, для них не выполняется разрешение времени выполнения, поэтому в цепочке наследования значение переменной ссылочного класса используется при доступе вместо типа объекта , Я проверил его с дальнейшим расширением классов и использованием промежуточного ссылочного типа. Спасибо за ответ. –

45

Когда вы делаете переменную с тем же именем в подклассе, это называется , скрывая. В результате подкласс теперь будет иметь как. Вы можете получить доступ к одному из суперкласса с помощью super.var или ((SuperClass)this).var. Переменные не обязательно должны быть одного типа; это всего лишь две переменные, разделяющие имя, подобно двум перегруженным методам.

+0

Спасибо за ответ. –

+0

Итак, делать это не полиморфизм. Означает ли это, что концепция «скрытия данных» ООП? –

+0

@RahulRastogi Нет, это не имеет ничего общего с этой концепцией. «Скрытие данных» - это инкапсуляция. –

8

Переменные разрешены время компиляции, методы выполнения. ARef имеет тип A, поэтому aRef.Intvalue - это время компиляции, разрешенное к 1.

+0

Спасибо за ответ –

0

В соответствии с спецификациями Java переменные экземпляра не переопределяются из суперкласса подклассным классом при его расширении.

Следовательно, переменную в подклассе можно рассматривать только как одно с тем же именем.

Также, когда конструктор A вызывается во время создания экземпляра B, переменная (intVal) инициализируется и, следовательно, выводится.

+0

Я не получил первый балл. Мы всегда можем получить доступ к любым неединичным переменным-членам суперкласса в подклассе. –

0

Ну, надеюсь, у вас есть ответ. Если нет, вы можете попробовать посмотреть в режиме отладки. подкласс B имеет доступ как к intVal. Они не являются полиморфными, поэтому они не переоцениваются.

Если вы используете ссылку B, вы получите intVal B. Если вы используете ссылку A, вы получите intVal. Это так просто.

+0

В режиме отладки я вижу, что и b, и aRef имеют как intVal s, тогда как в соответствии с вашим комментарием я ожидал, что только объект b будет иметь оба значения. Это потому, что отладчик ведет себя иначе, чем JVM? –

+0

Наверное, было недоразумение. До того момента, когда вы не присвоили b aRef, у него был только один intVal.Когда вы назначили b в aRef, теперь он указывает на объект типа B, следовательно, на два intVals. – dharam

+0

Спасибо за ответ –

-1

Java имеет перо инкапсуляции означает, что он тесно связывает свойство и поведение объекта. поэтому только через ссылку на класс мы можем назвать это поведение, чтобы изменить его свойство.

и только в режиме наследования переопределяет, так что он может влиять только на его свойство.

2

От JLS Java SE 7 Издания §15.11.1:

Отсутствия динамического поиска для поля обращающегося позволяет программы эффективно работать с простыми реализациями. Возможность позднего связывания и переопределения доступна, но только при использовании методов экземпляра.

Ответы от Oliver Charlesworth и Марко Топольник правильны, я хотел бы остановиться немного больше на почему часть вопроса:

В Java class members являются доступ по типу ссылка, а не тип фактического объекта.По той же причине, если у вас есть someOtherMethodInB() в классе B, к нему не будет доступ к нему с aRef после запуска aRef = b. Идентификаторы (то есть имена классов, переменных и т. Д.) Разрешаются во время компиляции, и поэтому для этого используется компилятор для ссылочного типа.

Теперь в вашем примере при запуске System.out.println(aRef.intVal); он печатает значение intVal, определенное в A, потому что это тип ссылки, которую вы используете для доступа к ней. Компилятор видит, что aRef имеет тип A, и это intVal, к которому он будет обращаться. Не забывайте, что у вас есть как полей в случаях B. JLS также имеет пример, похожий на ваш, «15.11.1-1. Статическое привязку для доступа к полям», если вы хотите взглянуть.

Но почему методы ведут себя по-другому? Ответ заключается в том, что для методов Java использует позднее связывание. Это означает, что во время компиляции он находит наиболее подходящий метод для для поиска во время работы. Поиск включает случай переопределения метода в некотором классе.

3

Полиморфизм полей в Java отсутствует.

Variables решение происходит во время компиляции, поэтому всегда переменные базового класса (наследственные переменные не ребенка) будет доступ.

Поэтому, когда происходит всегда приведение к базовому типу помнить

1) переменные базового класса будут доступны.

2) Будут вызываться методы подкласса (переопределенные методы, если переопределение произошло иначе, унаследованные методы, как и от родителя).

0
OverRiding Concept in Java 
Functions will override depends on object type and variables will accessed on reference type. 

1. Override Function: In this case suppose a parent and child class both have same name of function with own definition. But which function will execute it depends on object type not on reference type on run time. 

For e.g.: 
Parent parent=new Child(); 
parent.behaviour(); 
//in that case parent is a reference of Parent class but holds the object of Child Class so thats why Parent class function will call in that case. 

Child child=new Child(); 
child.behaviour(); 
//in that case child holds the object of Child Class so thats why Child class function will call in that case. 

Parent parent=new Parent(); 
parent.behaviour(); 
//in that case parent holds the object of Parent Class so thats why Parent class function will call in that case. 

2. Override Variable: Java supports overloaded variables. But actually these are two different variables with same name. One in parent class ad second in child class. And both variable can be either of same datatype or different. 

When you trying to access the variable, it depends on reference type object not depends on object type. 

For e.g.: 
Parent parent=new Child(); 
System.out.println(parent.state); 

//in that case reference type is Parent so Parent class variable is accessed not Child class variable. 

Child child=new Child(); 
System.out.println(child.state); 

//in that case reference type is Child so Child class variable is accessed not Parent class variable. 

Parent parent=new Parent(); 
System.out.println(parent.state); 

//in that case reference type is Parent so Parent class variable is accessed not Child class variable. 

Я надеюсь, что это решение поможет вам. Благодаря

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