– Cześć, Amigo! Dzisiaj dokonasz wielu odkryć. Temat na dziś — werble — to interfejsy.
– Jasne. Zapowiada się tak ciekawie, że lecę do domu wziąć kąpiel.
– Interfejs jest potomkiem Abstrakcji i Polimorfizmu. Interfejs jest bardzo podobny do klasy abstrakcyjnej, w której wszystkie metody także są abstrakcyjne. Jest deklarowany w ten sam sposób co klasa, ale wraz ze słowem kluczowym interface
. Oto kilka przykładów:
Kod | Opis i fakty |
---|---|
|
1) Zamiast słowa class piszemy interface . 2) Zawiera on tylko metody abstrakcyjne (nie trzeba dodawać słowa abstract). 3) W rzeczywistości wszystkie metody interfejsów są publiczne. |
|
Interfejs może dziedziczyć tylko inne interfejsy. Można mieć wiele macierzystych interfejsów. |
|
Klasa może dziedziczyć wiele interfejsów (i tylko jedną klasę). Aby pokazać to dziedziczenie, używamy słowa kluczowego implements . Klasa Innymi słowy, |
– Interesujące. Po co są nam te interfejsy? Kiedy się ich używa?
– Interfejsy mają przewagę nad klasami w dwóch ważnych aspektach.
1) Rozdzielenie „definicji metod” od ich implementacji.
Poprzednio powiedziałem Ci, że jeśli chcesz pozwolić innym klasom wywoływać metody Twojej klasy, to musisz je oznaczyć jako public
. Jeśli chcesz, aby pewne metody były wywoływane tylko z Twojej własnej klasy, to muszą one być oznaczone jako private
. Innymi słowy, dzielimy metody klasy na dwie kategorie: «dla wszystkich» i «tylko dla mnie».
Za pomocą interfejsów jeszcze bardziej wzmacniamy ten podział. Możemy utworzyć specjalną „klasę dla wszystkich”, która będzie dziedziczyć drugą „klasę tylko-dla-mnie”. Wyglądałoby to tak:
class Student
{
private String name;
public Student(String name)
{
this.name = name;
}
public String getName()
{
return this.name;
}
private void setName(String name)
{
this.name = name;
}
interface Student
{
public String getName();
}
class StudentImpl implements Student
{
private String name;
public StudentImpl(String name)
{
this.name = name;
}
public String getName()
{
return this.name;
}
private void setName(String name)
{
this.name = name;
}
}
public static void main(String[] args)
{
Student student =
new Student("Alibaba");
System.out.println(student.getName());
}
public static void main(String[] args)
{
Student student =
new StudentImpl("Ali");
System.out.println(student.getName());
}
Rozbijamy naszą klasę na dwie części: interfejs i klasę, która ten interfejs implementuje.
– To jakie ma to zalety?
– Ten sam interfejs może być implementowany (dziedziczony) przez różne klasy. A każda klasa może mieć swoje własne zachowanie. Tak, jak ArrayList i LinkedList są dwiema różnymi implementacjami interfejsu List.
Zatem, ukrywamy nie tylko różne implementacje, ale także klasy zawierające implementacje (możemy po prostu użyć interfejsów w każdym miejscu kodu). To pozwala nam w elastyczny sposób, w trakcie działania programu, zastąpić pewne obiekty innymi, zmieniając zachowanie obiektu bez wiedzy klas, które go używają.
W połączeniu z polimorfizmem stanowi to bardzo potężne narzędzie. W tej chwili jeszcze może nie zrozumiesz, do czego jest to potrzebne. Musisz najpierw natknąć się na program składający się z dziesiątek bądź setek klas, aby docenić to, jak bardzo interfejsy mogą Ci ułatwić życie.
2) Wielokrotne dziedziczenie.
W Javie każda klasa ma tylko jedną klasę macierzystą. W innych językach programowania klasy mogą często mieć wiele klas macierzystych. To bardzo wygodne, ale niestety tworzy też swoje problemy.
Java oferuje nam kompromis: nie można dziedziczyć wielu klas, ale można implementować wiele interfejsów. Interfejs może mieć wiele interfejsów macierzystych. Klasa może implementować wiele interfejsów i dziedziczyć tylko jedną klasę macierzystą.
GO TO FULL VERSION