Почему я не могу обратиться к полю класса-наследника в Java?

Есть два класса, один наследник другого:

public class myClass1 {}

public class myClass2 extends myClass1 {
    public int x;
}

Почему, записав в переменную типа myClass1 ссылку на объект myClass2 я не могу обратиться к полю x принадлежащему myClass2?

public class Go {
    public static void main(String[] args) {
        myClass1 c1 = new myClass2();
        c1.x = 10; //ОШИБКА
    }
}

Ответы (1 шт):

Автор решения: Nowhere Man

Простой ответ: потому что в классе-предке myClass1, к которому относится переменная c1, поле x "отсутствует".

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

То есть, объявив переменную с классом-предком myClass1, программист согласился, что свойства/методы, определённые в подклассах, его не интересуют.

Если очень надо обратиться к свойству/методу подкласса через ссылку на класс-предок, можно воспользоваться операцией приведения типа, которая может выбросить исключение ClassCastException, для защиты от которого понадобится проверить тип, например при помощи instanceof:

if (c1 instanceof myClass2) {
    ((myClass2) c1).x = 10;
}
→ Ссылка