Это станет намного понятнее, если вы дадите своим классам более подходящие имена.
Важно помнить следующее: наследование означает специализация : подкласс - это особый вид его суперкласса.
Теперь вы понимаете, почему class Father
и class Son extends Father
действительно неправильны: a Son
равен , а не a (особый вид) Father
.
Вместо Father
и Son
, давайте использовать Animal
и Cat
:
class Animal {
public void makeSound() {
System.out.println("Beep!");
}
}
class Cat extends Animal {
@Override
public void makeSound() {
System.out.println("Miaow!");
}
}
Теперь легче понять, что они означают:
Animal c1 = new Animal(); // 1
Cat c2 = new Cat(); // 2
Animal c3 = new Cat(); // 3
Cat c4 = new Animal(); // 4 WRONG!
A Cat
является Animal
, поэтому в (3) разрешено присваивать объект Cat
переменной типа Animal
- Cat
, гарантированно иметь всеметоды, доступные на Animal
.Итак, любой метод, который вы могли бы вызвать c3
, существует в объекте, к которому относится c3
.
С другой стороны, присваивая Animal
переменной типа Cat
, как в (4), недопустимо, поскольку у класса Cat
могут быть дополнительные методы, которые нельзя вызвать для объекта Animal
.Если (4) разрешено, вы можете попытаться вызвать эти методы, что не должно быть возможно.