Twój kod i przykład jest za prosty, żeby zobaczyć sens polimorfizmu. Dodatkowo interfejs Pojazd to bardzo kiepski interfejs.
**Interfejs ** powinien opisywać - co chciałbyś z obiektem zrobić.
Załóżmy np. że chciałbyś zapisywać do pliku Identyfikator przejeżdzającego pojazdu. Bo np. robisz oprogramowanie dla Parkingu.
I mogłbyś napisać metodę: (uwaga kody nie są kompletne i się nie kompilują)
public void zapisz(Samochód jakisSamochod) {
...
plik.write("identyfikator to:" + jakisSamochód.dawajNoTabliceRejestracyjną());
}
I powiedzmy, że masz już taki samochód to mozesz wtedy tą metodę wywołać:
Samochod mojaUlubionaŁada = new Łada("KSU 8590");
//i potem
zapisz( mojaUlubionaŁada);
działa proste. I nie ma interfejsów. I dobrze.
Ale załóżmy, żę twój parkingowy interes się rozkręca i teraz wchodzisz na rynek międzyplnetarny. Mogą już parkować nie tylko samochody, ale tez rakiety (ba !na jednym parkingu. I rozlicza się wszystko w jednym automacie (pozostaje pytanie jak zrobisz szlaban wyjazdowy dla rakiety, ale to problem gości od hardware).
No i ląduje jakiś Bogdan swoją rakietą.
Rakieta rakietaBogdana = new Orzeł(7);
I chcesz zapisać numery rejestracyjne... a tu problem metoda zapisz potrzebuje Samochodu... Pech.
Ale w sumie wiemy, że to hipotetyczny problem, bo byłeś sprytny i tak naprawdę zrobiłeś metodę zapisz tak:
public void zapisz(IdentyfikowalnaRzecz cośTam) {
...
plik.write("identyfikator to:" + cośTam.dawajNoIdentyfikator());
}
Wtedy Samochod i Rakieta wyglądają tak:
class Samochód implements IdentyfikowalnaRzecz {
private final String tablica;
...
public String dawajNoIdentyfikator() {
return this.tablica;
}
}
class Rakieta implements IdentyfikowalnaRzecz {
priate final int id;
...
public String dawajNoIdentyfikator() {
return this.getTyp()+ ":" + this.is ;
}
abstract String getTyp() ;
}
class Orzeł extends Rakieta {
..
Strign getTyp() {
return "Orzeł";
}
}
Przy okazji Orła widać, że klasy implementujące interfejsy mogą dodawać własne metody, czasem jest to użyteczne, wskazane.
A co z implementowaniem dwóch lub więcej interfejsów. To tak np. jakbyś miał w parkingu jeszcze jedną usługe - mycie.
I wtedy piszesz metodę -
CośCzystego myj (CośUmywalnego brudnaRzecz) {
return susz(polejWodą(woskowanie(polejWodą(szamponem(polejWodą(brudnaRzecz))))));
}
No i wtedy np. Samochód implements CośIdentyfikowalnego, CośUmywalnego
i Rower też,
a Rakieta nie (bo brud i tak odpadnie przy wchodzeniu w atmosferę).