А логика в том, что если у тебя и у кошки и у собаки есть одинаковый метод, voice родителя, который в одном случае говорит гаф, а в другом мяу. То ты можешь написать метод, каоторый принимает Animal и вызывает у него voice и получить разные результаты.
Так что кот, что собака, они оба наследники животного, у которого есть метод войс. Но в чем разница, если мы напишем:
Dog dog = new Dog
Он получит метод войс в любом случае, т.к. родитель Animal
Но вместо этого, мы пишем Animal animal = new Dog
И даже если мы теперь создадим:
Dog dog = new Dog
Cat cat = new Cat
dog.voice()
cat.voice()
отработает оба метода т.к. это два разных обьекта