Создание объектов подкласса как экземпляров суперкласса в Java

1

скажем, у меня есть следующий код (это вопрос викторины, поэтому я могу запустить его в своей среде IDE, но логика его работы не совсем понятна):

public class Test {

    public static void main(String[] args){
        A aInstance1 = new A();
        A aInstance2 = new B();
        A aInstance3 = new C();
        aInstance1.doSth();
        aInstance2.doSth();
        aInstance3.doSth();
    }
}

class A {
    public static void doSth(){
        System.out.println("Doing something in A");
    }
}
class B extends A {
    public static void doSth(){
        System.out.println("Doing something in B");
    }
}

class C extends B {
    public static void doSth(){
        System.out.println("Doing something in C");
    }
}

Выход будет следующим:

Выполнение чего-то в A

Выполнение чего-то в A

Выполнение чего-то в A

Таким образом, мой первый вопрос: в чем смысл декларации типа

A aInstance2 = new B();

т.е. почему создать объект класса B, объявив его экземпляром класса A? Как свойства aInstance2 как объекта класса B изменяются по сравнению с объявлением

B aInstance2 = new B();

?

Если я удалю слово static из объявления методов doSth() в классах A, B и C, выход изменится на

Выполнение чего-то в A

Выполнение чего-то в B

Выполнение чего-то в C

Таким образом, когда методы были статическими, метод doSth() класса A не был переопределен теми из подклассов, и вывод всегда был "Выполнение чего-то в A", созданного объектами разных классов, тогда как когда он стал экземпляр (нестатический) метод, он становится переопределенным (если я использую правильный термин здесь). Почему это так?

  • 2
    stackoverflow.com/questions/2223386/...
  • 0
    Смотрите также stackoverflow.com/questions/383947/…
Показать ещё 1 комментарий
Теги:
inheritance

5 ответов

1

Переопределение зависит от наличия экземпляра класса. Статический метод не связан ни с одним экземпляром класса, поэтому концепция не применима.

Статические методы работают быстрее, потому что нет необходимости ждать времени выполнения, чтобы выяснить, какой метод вызывать.

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

Иллюстрация -

  • Когда doSth() статичен:

    A aInstance1 = new A();
    A aInstance2 = new B();
    A aInstance3 = new C();
    aInstance1.doSth();
    aInstance2.doSth();
    aInstance3.doSth();
    

В приведенном выше коде компилятор будет решать во время компиляции, чтобы без экземпляра его нужно было вызвать для A. Нет переопределения.

  • Когда doSth() не является статическим:

    A aInstance1 = new A();
    A aInstance2 = new B();
    A aInstance3 = new C();
    aInstance1.doSth();
    aInstance2.doSth();
    aInstance3.doSth();
    

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

1

Статические методы - это методы класса, а нестатические - это методы экземпляра. Поэтому, когда вы вызываете статический метод над экземпляром, вы на самом деле вызываете его по объявленному типу этого экземпляра. Таким образом, все приведенные ниже вызовы фактически выполняют один и тот же вызов: A.doSth() поскольку все экземпляры объявляются как тип A.

aInstance1.doSth();
aInstance2.doSth();
aInstance3.doSth();

Когда вы удаляете статическое ключевое слово, doSth() становится методом экземпляра. Методы экземпляра выполняются над объектами вместо классов. Более того, когда вы повторно объявляете метод экземпляра в подклассе, этот метод переопределяется подклассом. В вашем примере класс B и C переопределяют doSth(). Таким образом, каждый класс обеспечивает свою собственную реализацию.

1

Удаляя слово static, вы делаете динамическое связывание, потому что вы в значительной степени говорите: "Даже если я знаю, что этот объект имеет тип A, я хочу, чтобы он вел себя как B".

Добавление слова static означает, что вы делаете этот метод частью класса [Тип ссылки], и каждый раз, когда вы вызываете: "Досмт()" он знает, что он применяется только к A, поэтому он показывает результат mothod из класса A.

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

Если вы не возражаете, я отправлю ссылку на информацию о Static и Dynamic Binding http://javarevisited.blogspot.ro/2012/03/what-is-static-and-dynamic-binding-in.html

1

Поскольку статический метод основан на типе Reference.

aInstance1.doSth();
aInstance2.doSth();
aInstance3.doSth();

Поэтому он внутренне преобразуется в:

A.doSth();
A.doSth();
A.doSth();
0

статические методы находятся на уровне class и действуют на ссылочный тип (LHS of ==) в отличие от методов уровня экземпляра, которые динамически отправляются на основе типа экземпляра (RHS of ==)

Ещё вопросы

Сообщество Overcoder
Наверх
Меню