Почему java ref vars вызывают метод, основанный на реальном объекте, где переменные основаны на типе переменной ref? - PullRequest
2 голосов
/ 29 июля 2011

И в суперклассе A, и в подклассе B у меня есть переменная abc как 10 и 20 соответственно, и метод callme (), переопределенный в подклассе.

Если я делаю

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

тогда, если я напишу

a.callme() -> calls B's method
b.callme() -> calls A's method. 

Это потому, что метод вызывается на основе фактического объекта.

Если я делаю

str = a.abc; // will print 10 , based upon ref var type A

str = b.abc; // will print 20 , based upon ref var type B

Почему это различие?Почему нет доступа к методам и переменным в зависимости от фактического объекта?

Спасибо

Ответы [ 2 ]

2 голосов
/ 29 июля 2011

Помните, переменные экземпляра никогда не переопределены , они скрыты .Это тип ссылки, который решает, чьи переменные экземпляра будут доступны.

В подклассе метод callme() переопределен.Таким образом, в соответствии с механизмом отправки динамических методов , именно тип объекта определяет, какой метод будет вызван во время выполнения.Это потому, что объекты создаются во время выполнения.

Например,

class A {
       int abc = 10;

       public void callme() { 
           System.out.println("In class A");
        }
   }

class B extends A {   
       int abc = 20;  // hidden, not overidden

        public void callme() { 
           System.out.println("In class B");
        }

        public static void main(String [] args) {
        A a = new A();
        a.callme(); // calls A's callme() method. 

        B b = new B();
        b.callme(); // calls B's callme() method.
       }
 }
0 голосов
/ 29 июля 2011

Методы имеют реализацию, в то время как поля просто хранят значения / объекты. Имеет смысл переопределить реализацию метода. Но я не вижу необходимости «переопределять» поле. Почему бы просто не удалить объявление из подкласса и использовать поле суперкласса?

С другой стороны, также можно скрыть методы. Но вы должны сделать их личными.

class OuterClass {
    void test() {
        InnerSubClass isc = new InnerSubClass();
        isc.m(); // prints "In subclass"
        ((InnerSuperClass) isc).m(); // prints "In superclass"
    }
    class InnerSuperClass {
        private void m() {
            System.out.println("In superclass");
        }
    }
    class InnerSubClass extends InnerSuperClass {
        private void m() {
            System.out.println("In subclass");
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...