OK, to może mały przykład jeszcze.
Załóżmy, że mamy abstrakcyjną klasę Vechicle
, która ma pewne typowe dla pojazdów własności enginePower, maxSpeed
itp. Rozszerza ją klasa FlyingVechicle
w klasycznym modelu dziedziczenia powiemy FlyingVechicle is a Vechicle
czyli jest typu Vechicle
Teraz anlogicznie mamy rodzinę klas z bazową klasą Animal
, która ma zupełnie inne właściwości niż obiekty klasy Vechicle
i próbowanie łączenia pojazdów i zwierząt w hierachie klas w sposób oczywisty jest niemożliwe, tudzież prowadzi to katastrofy.
Z klasy Animal dziedziczy dlaej FlyingAnimal
, znowu powiemy FlyingAnimal is an Animal
.
Obiekty typu FlyingAnimal
i FlyingVechicle
mają jednak jedną wspólną cechę - latają (poz tym nic je nie łączy). Teraz powiedzmy, że chcielibyśmy żeby te latające obiekty miały ze sobą coś wspólnego. Z pomocą przychodzą tu interfejsy. Zróbmy sobie interfejs Flyable
, który zaimplementujemy w naszych latających klasach FlyingAnimal
i FlyingVechicle
.
Kopiuj
public interface Flyable {
default void fly(){
System.out.println("fly baby");
}
}
Interfejs to umowa, mówi do swojego klienta - "masz latać", a klient mówi "ok będę latał, umowa stoi."
W naszych klasach możemy przedefniować metodę fly, albo zostawić ją domyślną tj bez konieczności implementacji.
Ponieważ interfejs jest również typem nadrzędnym, dla klas, które go implementują zatem możemy to wykorzystać i na przykład zrobić sobie kolekcję typu Flyable
.
Kopiuj
FlyingAnimal flyinAnimal= new FlyingAnimal();
FlyingVechicle flyingVechicle = new FlyingVechicle();
List<Flyable> flyables = new ArrayList<>();
flyables.add(flyingVechicle);
flyables.add(flyinAnimal);
flyables.forEach(f -> f.fly());