Polimorfizm

Korzyści jakie możemy osiągnąć z tytułu dziedziczenia byłyby bardzo ograniczone, gdyby nie polimorfizm. Polimorfizm oznacza możliwość traktowania obiektów różnych podtypów pewnego wspólnego typu w taki sam sposób. Za chwilkę przekonamy się, co to oznacza i jak bardzo potrafi ułatwić programowanie.

Wróćmy na chwilę do przykładu z artykułu dotyczącego dziedziczenia. Skoro książka jest produktem – w języku Java oznacza to, że klasa Book dziedziczy z klasy Product – to przecież możemy potraktować książkę jak produkt. Skoro możemy książkę potraktować jak produkt, to możemy obiekt reprezentujący konkretną książkę, a więc obiekt typu Book, przypisać do referencji typu Product. Możemy więc napisać:

Product myProd = new Book(39.90, 210);

Oczywiście w naszym sklepie będziemy sprzedawali też inne artykuły, nie tylko książki. Będziemy więc mieli także klasy takie jak MusicCDGameCD AppCD opisujące kolejno płyty CD czy DVD z muzyką, grami i aplikacjami. Wszystkie one będą dziedziczyły z klasy Product i wszystkie one mogą być przetwarzane w systemie tak jak produkty. Możemy więc napisać:

Product myProd = new MusicCD(19.90, "The Beatles", "A Hard Day's Night");

i potem:

myProd.getPrice();

Wyobraźmy sobie teraz, że chcemy zaimplementować w naszej aplikacji sklepu internetowego koszyk, który przechowuje wybrane przez klienta artykuły i który potrafi odpowiedzieć na pytanie – jaka jest łączna wartość zamówienia. Aby policzyć wartość zamówienia trzeba zsumować ceny poszczególnych produktów, niezależnie od tego, jakiego typu są te produkty. Wygodnie jest móc traktować wszystkie obiekty reprezentujące produkty takie jak książki, płyty muzyczne, gry i wszelakie inne w ten sam sposób. Możemy wówczas przejrzeć kolekcję produktów z koszyka i dla każdego z nich wywołać metodę getPrice(). Suma wyników będzie wartością zamówienia.

Łącząc ze sobą mechanizm polimorfizmu i przesłaniania metod możemy osiągnąć jeszcze ciekawsze rezultaty. Przykładowo, możemy zdefiniować produkt BonusPackage, tj. produkt, który jest zbiorem dowolnych innych produktów oferowanych w pakiecie po promocyjnej cenie. Moglibyśmy wówczas w klasie BonusPackage przesłonić implementację metody getPrice() tak, aby metoda ta sumowała ceny wszystkich produktów z pakietu i na końcu odejmowała od tej sumy np. 10%.

Zauważmy, że wprowadzenie produktu BonusPackage nie pociąga za sobą w skutkach konieczności zmiany klasy opisującej koszyk i funkcjonalności liczenia wartości zamówienia. Tak jak do tej pory sumujemy wyniki wywołania metody getPrice() dla każdego obiektu. Z punktu widzenia tego algorytmu jest nie istotne, że niektóre z tych obiektów, te które są typu BonusPackage mają zmienioną implementację metody getPrice().