Cześć! Dziś kończymy cykl wykładów na temat zasad OOP . Na tej lekcji porozmawiamy o polimorfizmie. Polimorfizm to zdolność do traktowania wielu typów tak, jakby były tego samego typu. W tym przypadku zachowanie obiektów będzie się różnić w zależności od tego, do jakiego typu należą. Przyjrzyjmy się temu stwierdzeniu bardziej szczegółowo. Zacznijmy od pierwszej części: „możliwość pracy z wieloma typami tak, jakby były tego samego typu”. Jak różne typy mogą być jednym i tym samym? Brzmi trochę dziwnie :/ To właściwie proste. Na przykład taka sytuacja powstaje przy normalnym korzystaniu z dziedziczenia. Zobaczmy jak to działa. Załóżmy, że mamy prostą klasę nadrzędną
Kiedy to „uogólnianie” nie jest wymagane, a wręcz przeciwnie, potrzebujemy, aby zachowanie gatunków było odmienne, każdy typ zachowuje się inaczej. Dzięki polimorfizmowi tworzysz jeden interfejs (zestaw metod) dla szerokiego zakresu klas. Z tego powodu złożoność programów jest zmniejszona. Nawet gdybyśmy rozszerzyli program na 40 typów kotów, nadal mielibyśmy najprostszy możliwy interfejs – jedną metodę
Cat
z jedną metodą run()
– „uruchom”:
public class Cat {
public void run() {
System.out.println("Бег!");
}
}
Stwórzmy teraz trzy klasy dziedziczące po Cat
: Lion
, Tiger
i Cheetah
, oznaczające lwa, tygrysa i geparda.
public class Lion extends Cat {
@Override
public void run() {
System.out.println("Лев бежит со prędkośćю 80 км/ч");
}
}
public class Tiger extends Cat {
@Override
public void run() {
System.out.println("Тигр бежит со prędkośćю 60 км/ч");
}
}
public class Cheetah extends Cat {
@Override
public void run() {
System.out.println("Гепард бежит со prędkośćю до 120 км/ч");
}
}
Mamy więc 3 klasy. Zasymulujmy sytuację, w której możemy z nimi pracować, jakby byli tą samą klasą. Wyobraźmy sobie, że jeden z naszych kotów jest chory i potrzebuje pomocy doktora Aibolita. Spróbujmy stworzyć klasę Aibolit
, która będzie w stanie leczyć lwy, tygrysy i gepardy.
public class Aibolit {
public void healLion(Lion lion) {
System.out.println("Лев здоров!");
}
public void healTiger(Tiger tiger) {
System.out.println("Тигр здоров!");
}
public void healCheetah(Cheetah cheetah) {
System.out.println("Гепард здоров!");
}
}
Wydawać by się mogło, że problem został rozwiązany – klasa jest napisana i gotowa do użycia. Ale co zrobimy, jeśli będziemy chcieli rozszerzyć nasz program? Teraz mamy tylko 3 gatunki: lwy, tygrysy i gepardy. Ale na świecie istnieje ponad 40 gatunków kotów. Wyobraź sobie, co się stanie, jeśli dodamy do programu osobne zajęcia dla kotów Pallas, jaguarów, Maine Coonów, kotów domowych i wszystkich innych. Sam program oczywiście będzie działał, ale klasa Aibolit
będzie musiała stale dodawać nowe metody leczenia każdego rodzaju kota, w wyniku czego urośnie do niespotykanych rozmiarów. W tym miejscu wchodzi w grę właściwość polimorfizmu - „zdolność pracy z kilkoma typami, jakby były tego samego typu”. Nie musimy tworzyć niezliczonych metod, które zrobią to samo – wyleczą kota. Jedna metoda będzie wystarczająca dla wszystkich przypadków jednocześnie:
public class Aibolit {
public void healCat(Cat cat) {
System.out.println("Пациент здоров!");
}
}
Do metody healCat()
możemy przekazać zarówno obiekty Lion
, jak i Tiger
obiekty Cheetah
- wszystkie to Cat
:
public class Main {
public static void main(String[] args) {
Aibolit aibolit = new Aibolit();
Lion simba = new Lion();
Tiger sherekhan = new Tiger();
Cheetah chester = new Cheetah();
aibolit.healCat(simba);
aibolit.healCat(sherekhan);
aibolit.healCat(chester);
}
}
Wyjście konsoli:
Пациент здоров!
Пациент здоров!
Пациент здоров!
W ten sposób nasza klasa Айболит
może pracować z różnymi typami, tak jakby były tego samego typu. Zajmijmy się teraz drugą częścią: „w tym przypadku zachowanie obiektów będzie się różnić w zależności od tego, do jakiego typu należą”. Tutaj też wszystko jest proste. W naturze wszystkie koty biegają inaczej. Różna jest co najmniej prędkość ich działania. Z naszych trzech pupili gepard jest najszybszy, natomiast tygrys i lew biegają wolniej. Oznacza to, że ich zachowanie jest inne. Polimorfizm nie tylko daje nam możliwość używania różnych typów jako jednego. Jednocześnie pozwala nie zapomnieć o dzielących je różnicach i zachowuje specyficzne dla każdego z nich zachowanie. Można to zrozumieć na tym przykładzie. Powiedzmy, że po udanym wyzdrowieniu nasze koty postanowiły trochę pobiegać, żeby to uczcić. Dodajmy to do naszej klasy Aibolit
:
public class Aibolit {
public void healCat(Cat cat) {
System.out.println("Пациент здоров!");
cat.run();
}
}
Spróbujmy uruchomić ten sam kod, aby leczyć trzy zwierzęta:
public static void main(String[] args) {
Aibolit aibolit = new Aibolit();
Lion simba = new Lion();
Tiger sherekhan = new Tiger();
Cheetah chester = new Cheetah();
aibolit.healCat(simba);
aibolit.healCat(sherekhan);
aibolit.healCat(chester);
}
A tak będzie wyglądał wynik:
Пациент здоров!
Лев бежит со prędkośćю 80 км/ч
Пациент здоров!
Тигр бежит со prędkośćю 60 км/ч
Пациент здоров!
Гепард бежит со prędkośćю до 120 км/ч
Tutaj wyraźnie widzimy, że specyficzne zachowanie naszych obiektów zostało zachowane, chociaż wszystkie trzy zwierzęta przekazaliśmy do metody, „uogólniając” każde z nich na Cat
. Dzięki polimorfizmowi Java doskonale pamięta, że to nie trzy koty, a mianowicie lew, tygrys i gepard, które biegają inaczej. To jest główna zaleta stosowania polimorfizmu – elastyczność . Kiedy musimy stworzyć jakąś funkcjonalność wspólną dla wielu typów, lwy, tygrysy i gepardy po prostu zamieniają się w „koty”. Każde zwierzę jest inne, ale w niektórych sytuacjach - kot to kot, nieważne do jakiego gatunku należy :) Tutaj mamy dla Was wideo potwierdzenie.
run()
na wszystkie 40 kotów.
GO TO FULL VERSION