Jak działa polimorfizm w tym kodzie

0

Witajcie,
próbuje zrozumieć istotę polimorfizmu. Skoro to traktowanie w ten sam sposób różnych danych, to zapewne chodzi o metodę writeFullName. No ale co dalej?


function Person() {
this.namw = "";
this.surname = "";
}

function Programme() {
     this.knownLanguage = "";
}

Programmer.protoype = new Person();

function writeFullName(p) {
     console.lg(p.name + " " + p.surname);
}

var a = new Person();
a.name = "Jan";
a.surname = "Kowalski";

var b = new Programmer();
b.name = "Mario";
b.surname = "Rossi";
b.knownLanguage = "JavaScript";

writeFullName(a);
writeFullName(b);
0

Czy ten kod działa? Masz literówki, które pozbawiają ten przykład sensu.

2

O polimorfizmie można mówić gdy tworzymy jednolity sposób obsługi danych różnego typu. Przykładowo masz obiekt Person i obiekt Programmer, a następnie masz metodę np. describe(), która dla obiektu Person wyświetli imię i nazwisko, a dla obiektu Programmer dodatkowo wyświetli np. język w którym programuje. Co istotne jeżeli użyjesz metody describe() obiektu po którym dziedziczysz na obiekcie typu, który po nim dziedziczy to nadal wszystko będzie działać czyli obiekt Programmer w kontekście klasy nadrzędnej Person przedstawi się tylko imieniem i nazwiskiem.

Pamiętaj, że ES6 wprowadził klasy, które ukrywają pod spodem prototypy. Z tego też powodu należy się nauczyć polimorfizmu w kontekście prototypów oraz klas. W obu przypadkach będzie to działać tak samo, ale zapis będzie nieco inny.

0

Warto przy tej okazji wspomnieć o Liskov Substitution Principle

  1. Invariants of the Supertype Must Be Preserved in a Subtype
  2. Preconditions Cannot Be Strengthened in a Subtype
  3. Postconditions Cannot Be Weakened in a Subtype.

Osobiście najczęściej spotykam się z naruszeniem pkt. 2. Czyli ktoś w klasie bazowej pozwala na wszystko, np. działania na liczbach, a w klasie dziedziczącej dodaje jakiegoś if'a, który pozwala tylko na liczby dodatnie.

1

To, co się dzieje w powyższym kodzie już dobrze wytłumaczył @Haskell, w sumie nie ma nic więcej do dodania. W JavaScript to trochę słabo widać, bo tutaj sprawdzanie typów odbywa się przez duck-typing, bo do funkcji możesz przekazać dosłownie wszystko. Ale trochę więcej o polimorfizmie:

Poly, czyli wiele (poligon - wielokąt, poliglota - osoba mówiąca w wielu językach)
Morph, czyli zmiana formy (z ang. to morph oznacza przemieniać, płynnie przechodzić z jednego obrazu w drugi).

Czyli polimorfizm, to możliwość posiadania tego samego interfejsu dla różnych typów.

Załóżmy, że mamy byt figura (geometryczna). Możemy mieć figury koło, kwadrat, prostokąt i trójkąt. Te figury różnią się miedzy sobą, ale każdy z tych bytów jest figurą, a w związku z tym ma pole powierzchni. Jeżeli mamy jakiś zbiór figur i chcemy poznać ich sumaryczne pole powierzchni, to dzięki polimorfizmowi wiemy, że każdy byt, jeżeli tylko jest figurą, to ma metodę do obliczenia pola powierzchni, którą możemy bezpiecznie użyć.

W JS moim zdaniem to bardzo trudno zrozumieć, bo nie ma interfejsów jako takich (znanych z Javy, PHP, czy C#), ale wyglądało by to mniej więcej tak:

class Triangle {
    constructor(a, h) {
        this.a = a;
        this.h = h;
    }

    area() {
        return 0.5 * this.a * this.h;
    }
}

class Rectangle {
    constructor(a, b) {
        this.a = a;
        this.b = b;
    }

    area() {
        return this.a * this.b;
    }
}

class Circle {
    constructor(r) {
        this.r = r;
    }

    area() {
        return Math.PI * Math.pow(this.r, 2);
    }
}

function calculateTotalArea(shapes) {
    let total = 0;
    
    for (shape of shapes) {
        if (typeof shape.area === 'function') { // <-- przykład duck typingu
            total += shape.area();
        }
    } 
    
    return total;
}

const shapes = [new Triangle(5, 10), new Rectangle(5, 10), new Circle(5)];

console.log(calculateTotalArea(shapes));

1 użytkowników online, w tym zalogowanych: 0, gości: 1