Interfejsy - po co?

0

Może wstyd się przyznać, ale mam 5 miesięcy stażu jako junior w Javie i... nie rozumiem idei kryjącej się za interface. Rozumiem techniczne różnice między klasą abstrakcyjną a interface, ale nie rozumiem co takiego wnoszą interface czego nie wnosi użycie klasy abstrakcyjnej? Ok, można implementować ich wiele, a dziedziczyć tylko po 1 klasie. Do tego gdzieś wyczytałem, że jest to coś w rodzaju kontraktu który dana klasa musi spełnić. Ale poza tym, co tak naprawdę głównie kryje się za ideą używania interface w javie?

0

Założmy, że piszesz system który cachuje dane - możesz to napisać bez interfejsów - ale wtedy nie będzie możliwości rozszerzania tego systemu a jak stworzysz interface np.

CacheDriverInterface
save(key, value)
load(key)

I napiszesz implementację dla np. systemu plików:
FileCacheDriver implements CacheDriverInterface

Wtedy ktoś wykorzysta w systemie twoją klasę, ale dostanie informację od kogoś tam, że chcecie teraz zapisywać cache w redisie. Biblioteka tego nie umożliwia, ale dzięki temu, że ma interfejs może napisać własne rozszerzenie np.
RedisCacheDriver

odpowiednio wstrzyknąć i nie musi przy tym zmieniać żadnej linijki kodu w obecnym systemie (który korzystał z FileCacheDriver).
To jest właśnie kontrakt.

Teraz może ktoś umieści RedisCacheDriver na np. github i inne firmy też będą mogły z tego korzystać.

Inna sytuacja:
Macie jakieś duże zadanie do zrobienia w firmie, na początku ustalacie jakiś interfejs wtedy możecie łatwo podzielić pracę, część osób pisze właściwe implementacje na podstawie interfejsu, inne osoby z niego korzystają (ale nie mają jeszcze właściwej wersji).

0

Odwracanie zależności - jeżeli tworzysz moduł i masz zewnętrzną zależność to możesz wystawić interfejs i po pierwsze nie być zależnym od implementacji, a po drugie ten interfejs zaimplementować gdzieś obok i nie zaśmiecać kodu biznesowego sprawami infrastrukturalnymi. Interfejsy dają kontrolę nad kierunkiem zależności w kodzie

Generalnie klasy abstrakcyjne sa spoko, do konkretnych zastosowań, ale pozwalają na zbyt wiele, np. dziedziczenie pól.

7

Parafrazując pewien przykład z SO który zapadł mi w pamięć- wyobraź sobie że masz klasę Motorcycle (która może dziedziczyc po Vehicle), klasę Mosquito (może dziedziczyc po Insect, Animal czy cokolwiek podobnego) oraz klasę Person. Teraz załóżmy że każdy z obiektów obojętnie którego z tych typów może dokuczać- motor jest głośny, komar wiadomo, człowiek krzyczy. Co za tym idzie każda z tych klas może posiadac metodę Annoy(). W zasadzie nie mają że sobą nic więcej wspólnego, jedyne co je łączy to możliwość dokuczania. Teraz napisz metodę która przyjmie obiekt obojętnie którego z tych typów i wywoła na tym obiekcie metodę Annoy().

0

Do czasu Javy 9 istniała ideologia w tym środowisku żeby separować wymagania od implementacji.
Nie ważne że masz tylko jedną implementację...
Były też jakieś problemy z wstrzykiwaniem nie-interfejsów.
Od Javy 9 w zasadzie różnica jest taka, że klasa może implementować n interfejsów (które mają implementacje), ale rozszerzać tylko jedną klasę.

Zwróć uwagę że w artykułach porównujących te twory często nie bierze się jeszcze pod uwagę metod domyślnych i tego że mogą być prywatne:
http://www.baeldung.com/new-java-9
https://docs.oracle.com/javase/9/whatsnew/toc.htm#JSNEW-GUID-825576B5-203C-4C8D-85E5-FFDA4CA0B346

0

Ja patrzę na różnice tak:

  • interfejs - rodzaj umowy między stronami, gdzie masz pewną swobodę w realizacji tego jak umowa zostanie wypełniona (tj. możliwość implementacji każdej operacji po swojemu)
  • klasa abstrakcyjna - może utrzymywać jakiś wewnętrzny stan i posiadać metody finalne (nie zezwalasz na modyfikację implementacji)
0

https://programmer-girl.com/2018/06/03/o-co-chodzi-z-odwroceniem-zaleznosci/

Tu jest fajny przykład jak można interfejsy wykorzystać

0

Interfejsy są po to, żeby:

  • dało się odwracać zależności (inversion of control, dependency injection)
  • dało się pisać klasy, które nie zależą od siebie bezpośrednio (komunikują się poprzez interfejsy)
  • dało się pisać testowalny kod (wynika to z powyższego punktu - można wtedy mockować interfejsy w testach)
  • dało się podmieniać implementacje bądź stosować jednocześnie wiele implementacji tego samego interfejsu w zależności od przypadku (np. wzorzec strategia)
0

Generalnie klasy abstrakcyjne mają tą wade że o wiele bardziej "wiążą zależności" niż interfejsy. No i oczywiście można robić dziedziczenie tylko po 1 klasie, ale to już wiesz

1 użytkowników online, w tym zalogowanych: 0, gości: 1