Наследование и ключевое слово "this" - PullRequest
12 голосов
/ 01 марта 2011

Предположим, что у нас следующая ситуация:

Родительский класс A:

class A{  
    public A(){}
    public doSomething(){  
        System.out.println(this.getClass());
    }
}

с дочерним классом B:

class B extends A{  
    public B(){}
    public void doSomething(){
        super.doSomething();
        System.out.println(this.getClass());
    }
}

и основным классом:

class Main{  
    public static void main(String[] args){
        A ab=new B();
        ab.doSomething();
    }
}

Когда я выполняю этот код, результатом является

B  
B

Почему this, на который ссылается суперкласс A, возвращает B как класс, когда ссылка имеет тип А?

Ответы [ 5 ]

16 голосов
/ 01 марта 2011

Неважно, что это за ссылка, важен класс экземпляра объекта. Создаваемый объект имеет тип B, поэтому this.getClass () всегда будет возвращать B.

3 голосов
/ 01 марта 2011

Несмотря на то, что вы вызываете метод doSomething() для A, this во время этого вызова является B, и поэтому метод getClass() вызывается на B, а не на A. В основном this всегда будет B независимо от того, используете ли вы метод из суперкласса A, метод из B или из суперкласса A Object (родительский класс всех классов Java) ).

1 голос
/ 01 марта 2011

Думайте об этом с точки зрения времени выполнения и статических типов:

Animal a = new Cat();

Статический тип (в данном случае записанный слева) переменной a равен Animal (вы не можете передать метод, который требует Cat без даункаста), но тип времени выполнения объекта, на который указывает a, равен Cat.

a.getClass() предоставляет тип времени выполнения (если он помогает думать о нем как о наиболее конкретном подтипе).

Интересно, что перегруженные методы Java разрешаются во время компиляции (без учета типа времени выполнения). Итак, с учетом следующих двух методов:

foo(Cat c);
foo(Animal animal)

Вызов foo(a) вызовет последнего. Чтобы исправить это, можно использовать шаблон посетителя для отправки на основе типа среды выполнения (двойная отправка).

1 голос
/ 01 марта 2011

this ничего не делает для вас в этой ситуации.Вызов this.getClass() ничем не отличается от вызова getClass();

Итак, A вызывает getClass (), который вернет B, если вы имеете дело с экземпляром B, который расширяет A.

0 голосов
/ 10 ноября 2017

Вывод программы правильный.

Когда в основном классе ab.doSomething (); будет выполняться вызов метода doSomething () класса B, затем super.doSomething (); строка вызовет метод doSomething () класса A. Поскольку это ключевое слово указывает на ссылку на текущий объект (ab - это объект класса B, см. A ab = new B (); как конструктор класса B), т.е. System.out.println (this.getClass ()); строка в классе A будет печатать только B.

Снова управление вернется к System.out.println (this.getClass ()); в классе B, так что снова B получит печать.

В виде птичьего глаза создан только объект класса B. Вот почему мы получаем B B на выходе.

...