Полиморфизм

Не так давно мы говорили о перезаписи методов родителя, что означает изменение имплементации в дочернем объекте. Сейчас это двинуло нас на очень важную и мощную концепцию в объектно-ориентированном программировании, которая называется — полиморфизм.

Poly — означает много, morph — означает форма.

Полиморфизм означает много форм. Это очень мощная техника в объектно-ориентированном программировании.

Возьмем пример с одной из прошлых статей

function extend(Child, Parent) {
    Child.prototype = Object.create(Parent.prototype);
    Child.prototype.constructor = Child;
}

function Shape() {
}

Shape.prototype.duplicate = function () {
    console.log('duplicate');
}

function Circle() {
}

extend(Circle, Shape);

Circle.prototype.duplicate = function () {
    console.log('duplicate circle');
}

const c = new Circle();

Определим новый shape объект под названием Square.
Как и Circle, Square также унаследуется от Shape.
Затем мы переопределим метод duplicate в Square объекте.

function Square() {}

extend(Square, Shape);

Square.prototype.duplicate = function () {
    console.log('duplicate square');
}

Теперь у нас есть проставя иерархия, где наверху у нас Shape и два дочерних класса. У каждого объекта своя имплементация метода duplicate. Т.е. у нас много имплементаций, или по другому, много форм метода duplicate. Вот почему это называется полиморфизм.

Так почему же это настолько мощная техника?

Давайте представим, что у нас есть массив объектов Shape. Теперь чтобы проитерироваться по массиву, воспользуемся for-of циклом.

const shapes = [
    new Circle(),
    new Square()
]

for (let shape of shapes) {
    shape.duplicate();
}

В зависимости от типа объект shape, разная имплементация, или разная форма метода duplicate будет вызвана. Итак, если эта фигура circle, то имплементация duplicate в circle объекте будет вызвана, и соответственно с square объектом та же история.

Перед тем как появилась ООП парадигма, если бы Вы захотели имплементировать данную логику, Вам бы пришлось писакать код как нижеприведенный.

for (let shape of shapes) {
    if (shape.type === 'circle') {
        duplicateCircle();
    } else if (shape.type === 'square') {
        duplicateSquare();
    } else {
        duplicateShape();
    }
}

Вам бы пришлось проверять тип объекта, и вызывать standalone функцию. Это не ООП путь написания кода. В ООП мы инкапсулируем наши переменные и функции в объекты.

Что если бы у нас было 10 таких типов?
По сравнению с ООП, когда мы инкапсулируем переменные и функции в объекты, и используем наследование, мы можем выполнять много форм метода, используя одну строчку кода.