![]()
W poprzednich lekcjach poznawałeś dziedziczenie i polimorfizm, klasy abstrakcyjne oraz agregację i kompozycję obiektów. Dzisiaj wykorzystamy te zagadnienia przy omawianiu interfejsów.
Interfejsy w Javie pozwalają określić, co klasa powinna robić, nie narzucając sposobu realizacji tych działań. W tym artykule dowiesz się, jak tworzyć interfejsy, implementować je w klasach i korzystać z ich zalet w elastycznym kodzie.
Wprowadzenie
Interfejsy umożliwiają oddzielenie definicji zachowania od jego implementacji, co sprawia, że kod jest prostszy w utrzymaniu i łatwiejszy do rozszerzania. Programiści mogą pracować na poziomie abstrakcji, wiedząc, jakie metody są dostępne, ale nie muszą interesować się szczegółami implementacji. Każdy interfejs pełni rolę kontraktu, który klasa implementująca musi wypełnić, co sprawia, że kod staje się spójny, przewidywalny i łatwiejszy do refaktoryzacji.
Interfejs
Najprościej, interfejs to umowa mówiąca klasie, jakie metody powinna posiadać. Interfejs nie przechowuje stanu i nie określa logiki działania metod, definiuje jedynie, co klasa powinna zrobić. W praktyce jest to zestaw metod abstrakcyjnych, które klasy implementujące muszą nadpisać. Pola w interfejsie, jeśli się pojawią, są automatycznie publiczne, statyczne i finalne, a wszystkie metody domyślnie publiczne i abstrakcyjne.
Na przykład interfejs Pojazd może definiować metody jedz() oraz zatrzymaj():
Przykład:

Słowo interface oznacza tworzenie interfejsu, a metody w nim nie mają ciała – jedynie deklarację. Każda klasa implementująca Pojazd dostarcza własną wersję tych metod, dzięki czemu różne typy pojazdów mogą zachowywać się zgodnie z kontraktem interfejsu, realizując go w indywidualny sposób.
Implementowanie interfejsu
Kiedy klasa decyduje się spełnić kontrakt interfejsu, używa słowa kluczowego implements.
Na przykład klasa Samochod implementuje interfejs Pojazd.
Przykład:


Jeśli jakakolwiek metoda pozostanie niezdefiniowana, kompilator wymusi jej implementację lub wymaga oznaczenia klasy jako abstract.
Interfejsy a polimorfizm
Interfejsy pozwalają wykorzystać polimorfizm. Możesz zadeklarować zmienną typu Pojazd i przypisać do niej różne obiekty, na przykład Samochod lub Rower. Kod operuje wtedy na interfejsie, a nie konkretnych klasach, co zwiększa elastyczność i ułatwia rozwój aplikacji.
Przykład:


Potem można podstawić inną klasę implementującą Pojazd, a kod nadal działa w taki sam sposób, niezależnie od konkretnego typu.
Metody domyślne i statyczne
Od Javy 8 interfejsy mogą zawierać metody domyślne, które dostarczają pewną implementację, ale nie wymagają nadpisania w klasach implementujących. Pozwala to dodawać nowe funkcje bez psucia istniejącego kodu.
Przykład:

Interfejsy mogą też posiadać metody statyczne, wywoływane podobnie jak w klasach:

Dla większego porządku można stosować metody prywatne, dzieląc logikę w interfejsie bez ujawniania jej na zewnątrz:

Interfejsy a wielodziedziczenie
Interfejsy mogą dziedziczyć po wielu innych interfejsach, a klasy mogą implementować wiele interfejsów. Wprowadzenie metod domyślnych stworzyło potencjalne konflikty, gdy dwa interfejsy mają metodę o tej samej sygnaturze. Java wymaga wówczas jawnego nadpisania metody w klasie implementującej, a jeśli chcemy odwołać się do konkretnej implementacji z interfejsu, używamy zapisu NazwaInterfejsu.super.nazwaMetody().
Przykład:
interface Rower {
default void pokazNazwe() {
System.out.println("Rower");
}
}
interface Motocykl {
default void pokazNazwe() {
System.out.println("Motocykl");
}
}
class ElektrycznyRower implements Rower {
@Override
public void pokazNazwe() {
System.out.println("Elektryczny Rower");
}
}
class SportowyMotocykl implements Motocykl {
@Override
public void pokazNazwe() {
System.out.println("Sportowy Motocykl");
}
}
Podsumowanie
Interfejsy w Javie to fundament programowania obiektowego, który porządkuje architekturę, wspiera polimorfizm i pozwala tworzyć kod elastyczny i łatwy w utrzymaniu. Definiując kontrakty w postaci interfejsów, programista zachowuje kontrolę nad strukturą aplikacji, minimalizując ryzyko chaosu w klasach. Interfejsy pozostają kluczowym elementem przy projektowaniu skalowalnych, przejrzystych i przewidywalnych systemów.
O autorze
Tester oprogramowania z pasją do jakości i technologii. Łączy doświadczenie w testach manualnych i automatycznych, koncentrując się przede wszystkim na aplikacjach webowych oraz usługach SOAP i REST. Testowanie to dla niego nie tylko szukanie błędów, ale przede wszystkim kwestionowanie przyjętych założeń i usprawnianie tego, co nie działa – również w samym procesie testowym. Lubi zmieniać, angażować się i aktywnie budować proces testowy, tak by miał sens, a nie tylko formę. Prywatnie fan rocka, biwakowania, podróży.

