Объяснить суть полиморфизма "на пальцах" довольно просто. Представьте себе класс
Телефон. Его спроектировал некто в далеких 80-х, и определил в нем метод
набратьНомер(). А потом другой программист в 90-х отнаследовал от него класс
МобильныйТелефон и перекрыл метод
набратьНомер(), т.к. грубо говоря, в новом устройстве набор производится уже не импульсно, а тонально. А потом третий программист отнаследовал от него класс
Смартфон. При этом он не стал трогать метод
набратьНомер(), а просто добавил методы для нового функционала, типа
определитьПоложениеПоGPS() и т.д.
Теперь представьте себе пользователя. Он родом из 80-х и понятия не имеет о тональном наборе и GPS... но если ему в руки дать любое из этих устройств, он сможет набрать номер и сделать звонок. Почему? Потому, что он умеет использовать метод
набратьНомер(), и большего ему знать не нужно.
А теперь представьте другого пользователя, нашего современника. Он вырос в эпоху смартфонов... но если ему в руки дать старый телефонный аппарат, он тоже сможет сделать звонок, т.к., опять же, знает метод
набратьНомер().
Применительно к ООП, пользователь - это переменная, содержащая ссылку на экземпляр класса. Ее тип (как она была объявлена) - это "набор знаний" о возможностях этого экземпляра. И т.к. Смартфон в своей основе является Телефон-ом, мы вполне можем дать его в руки гипотетическому пользователю из 80-х:
Телефон устройство = new Смартфон();
в результате чего он сможет сделать звонок:
устройство.набратьНомер("03");
А вот определить свое местоположение он не сможет, пока не узнает о существовании соотв. метода:
Смартфон усовершенствованноеУстройство = (Смартфон)устройство;
Это называется приведением типа. В данном примере у экземпляра класса уже был соотв. метод, но чтоб им воспользоваться, нужно сначала явно указать, что мы хотим рассматривать имеющееся у нас в руках устройство не как "простой" Телефон, а как Смартфон.
P.S. Кстати, в этом примере мы затронули не только полиморфизм, но и наследование, и инкапсуляцию (пользователя "снаружи" совершенно не интересует, как именно производится набор номера - тонально, импульсно или еще как-то иначе)... так сказать, все три кита ООП в одном флаконе. И только так вообще имеет смысл рассматривать эти принципы, т.к. они по сути неотделимы друг от друга, как Отец, Сын и Святой Дух в Христианстве или же длина, ширина и высота в трехмерном пространстве :) Если это понять, ООП становится совершенно простой и естественной парадигмой программирования.