Анонимный класс, Наследование и переопределение - PullRequest
4 голосов
/ 13 сентября 2011
public class A {
    public A() {
        foo();
    }

    private void foo() {
        System.out.print("A::foo ");
        goo();
    }

    public void goo() {
        System.out.print("A::goo ");
    }
}

public class B extends A {
public B() {
    foo();
}

public void foo() {
    System.out.print("B::foo ");
}

public void goo() {
    System.out.print("B::goo ");
}

    public static void main(String[] args) {

A b = new B() {
        public void foo() {System.out.print("Anonymous::foo ");}
        public void goo() {((B)this).foo();}
        };

}
}

Мне нужна ваша помощь с пониманием, почему программа печатает A::foo Anonymous::foo Anonymous::foo. Этот анонимный класс заменяет прежний B? переопределяет свои методы?

Как я понимаю, он должен перейти к конструктору A по умолчанию, запустить foo-print A "A :: foo", чем запустить goo B, поскольку он был правильно переопределен, но теперь goo B - это тот, который в классе Anonymous , так что он приводит это к B (который ничего не делает) и запускает свой foo, который является foo выше, для B, поэтому он должен вывести «Anonymous: foo». Что я делаю не так?

Большое спасибо.

Ответы [ 4 ]

4 голосов
/ 13 сентября 2011

Я думаю, что запутанная вещь здесь у вас есть два метода Foo. Один является частным, поэтому он не может быть переопределен, другой является общедоступным, поэтому его можно переопределить. B вызывает foo в своем конструкторе, но это переопределяется его подклассом.

4 голосов
/ 13 сентября 2011

Ваш вопрос не совсем ясен, но позвольте мне сказать, что ответ был бы точно таким же, если бы вместо анонимного класса, расширяющего B, у вас был класс верхнего уровня C, расширяющий B.Ничто в анонимных классах не заставляет их вести себя по-разному в отношении полиморфизма и наследования.Когда конструктор B вызывает foo(), вызывается основная версия наиболее производного класса - здесь анонимного класса.

3 голосов
/ 13 сентября 2011

Конструктор A вызывает A.foo (A :: foo), потому что он приватный и поэтому не перегружен. A.foo вызывает goo (), который был переопределен B, а затем Anonymous, поэтому вы получаете Anonymous.goo -> Anonymous.foo (Anonymous :: foo). Затем конструктор B вызывает foo, который переопределяется Anonymous, поэтому (Anonymous :: foo)

1 голос
/ 13 сентября 2011

Использование такого рода анонимной конструкции фактически создает подкласс B. Вы переопределили методы B с теми, которые вы предоставляете в анонимном классе, так что они будут использоваться вместо.

...