Bardzo dobre pytanie. Dla prawie każdej innej rzeczy w Javie znalazłem prawdziwy powód dla dokonanych wyborów, ale dla tego nie mam. Zdefiniowanie metody chronionej w interfejsie, który pozwala innej klasie w tym samym pakiecie na użycie tej metody na obiekcie implementującym, bez konieczności ujawniania tej metody, ma dla mnie sens, co nie może być przeznaczone do wywołania przez kogokolwiek innego niż członków pakietu do reszty świata.
Markus A.
4
@MarkusA. Ale interfejsy działają dwukierunkowo, tzn. Mogą być również implementowane przez klasy poza bieżącym pakietem (a następnie być może przekazywane jako argumenty do metod wewnątrz tego pakietu). W jaki sposób klasa spoza bieżącego pakietu mogłaby zaimplementować „chronione” metody jakiegoś publicznego interfejsu?
MartinStettner
8
@MartinStettner: Nie byłoby. To byłby punkt. Pakiet może mieć wiele niepowiązanych klas, które implementują interfejs i chcieć zagwarantować każdemu kodowi otrzymującemu odwołanie do tego typu interfejsu, że będzie się zachowywał w określony sposób. Taka gwarancja mogłaby być znacznie silniejsza, gdyby można było uniemożliwić zewnętrznemu kodowi twierdzenie, że implementuje interfejs, zachowując się w sposób sprzeczny z umową.
supercat
1
@MarkusA. podniosłeś dobry punkt, powinieneś być w stanie to osiągnąć dzięki systemowi modułów Java 9
Nir Alfasi
1
jeśli interfejs ma protectedmetodę, wszystkie klasy implementujące będą postrzegane jako podtyp interfejsu. a wszystkie te klasy MOGĄ mieć dostęp do metod chronionych. czy nie powoduje to, że protectedsłowo kluczowe w metodzie jest bezużyteczne? o ile nie mamy możliwości ograniczenia, kto implementuje ten interfejs, chronione słowo kluczowe w metodzie jest bezużyteczne. Popraw mnie, jeśli się mylę!
amarnath harish
Odpowiedzi:
67
Ponieważ interfejs ma oznaczać „to, co widać spoza klasy”. Nie ma sensu dodawać metod niepublicznych.
Ale dlaczego nie mieć funkcji, które tylko członkowie tego samego pakietu co interfejs „widzą spoza klasy”? Miałem kilka przypadków użycia, w których chciałem tego.
Markus A.
5
@MarkusA. Zdaję sobie sprawę, że to późno, ale wtedy możesz zrobić wszystko abstract class, co jest w interfaceporządku, i określić dowolny dostęp. Przyznane to traci korzyści z wielu implementacji, które interfacesą dostępne w Javie, ale uczciwe ustanowienie kontraktu, który jest zgodny z ograniczeniami jakiegoś innego pakietu, byłoby niesprawdzalne i mylące, ponieważ praktycznie nie byłbyś w stanie uzyskać dostępu do metody własnej implementacji poza tym pakietem .
pickypg
10
@pickypg Jeśli jednak klasa, która implementowałaby interfejs, rozszerza już inną klasę, nie można uczynić jej rozszerzeniem innej klasy. Nie uznałbym tego za mylące dla interfejsu, który jest używany tylko w pakiecie.
Flamma
24
@Raveline, -1, nasuwa się pytanie "dlaczego interfejs ma oznaczać to, co możesz zobaczyć spoza klasy?" Java 8 już pozwala na umieszczanie treści metod w interfejsach, więc dlaczego nie pozwolić również na chronione metody abstrakcyjne?
Pacerier
8
Często czytam to wyjaśnienie, ale jest źle IMHO. Interfejs to rodzaj „standardowego protokołu wymiany danych”, bez względu na to, czy chodzi o OOP, komunikacyjne API czy sprzęt. Port USB w moim komputerze jest wyraźnie interfejsem publicznym. Ale piny na mojej płycie głównej, czyli za obudową zamykaną na klucz, zapewniające dostęp do opcjonalnych portów USB, są wyraźnie „chronionym” interfejsem. Następnie mamy układ BIOS - który jest również standardowym interfejsem, ale nigdy nie jest w żaden sposób upubliczniany, tylko kilka firm zna dokładne szczegóły prywatnie. Oczywiście interfejsy mogą mieć dowolną widoczność! Dlaczego nie w OOP?
Foo Bar
55
Chociaż często przytaczanym powodem jest to, że „interfejsy definiują publiczne API”, myślę, że jest to nadmierne uproszczenie. (I "pachnie" też logiką kolistą.)
Nie byłoby bez sensu posiadanie interfejsów zawierających mieszankę modyfikatorów dostępu; np. częściowo publiczne, a częściowo ograniczone do innych klas w tym samym pakiecie co interfejs. W rzeczywistości w niektórych przypadkach może to być przydatne w dół, IMO.
Właściwie uważam, że częścią rozumowania stojącego za upublicznieniem elementów interfejsu jest to, że upraszcza to język Java :
Niejawnie publiczne elementy składowe interfejsu są prostsze w obsłudze dla programistów. Ile razy widziałeś kod (klasy), w którym modyfikatory dostępu do metody były wybierane pozornie losowo? Wielu „zwykłych” programistów ma trudności ze zrozumieniem, jak najlepiej zarządzać granicami abstrakcji Javy 1 . Dodanie publicznego / chronionego / prywatnego pakietu do interfejsów sprawia, że jest to jeszcze trudniejsze.
Niejawnie publiczne elementy interfejsu upraszczają specyfikację języka ... a tym samym zadanie dla autorów kompilatorów Java i osób, które implementują interfejsy API Reflection.
Myślenie, że „interfejsy definiują publiczne API” jest prawdopodobnie konsekwencją (lub cechą) decyzji dotyczącej projektu uproszczenia języka ... a nie na odwrót. Ale w rzeczywistości te dwa nurty myślenia prawdopodobnie rozwinęły się równolegle w umysłach projektantów Javy.
W każdym razie oficjalna odpowiedź na RFE w JDK-8179193 jasno pokazuje, że zespół projektowy Java zdecydował 2, że dopuszczenie protectedinterfejsów zwiększa złożoność i przynosi niewielkie realne korzyści. Uznanie dla @skomisa za znalezienie dowodów .
Dowody w RFE rozwiązują problem. To jest oficjalny powód, dla którego nie został dodany.
1 - Oczywiście programiści z najwyższej półki nie mają z tym trudności i mogą z zadowoleniem przyjąć bogatszą paletę funkcji kontroli dostępu. Ale co się stanie, gdy ich kod zostanie przekazany komuś innemu w celu utrzymania?
2 - Możesz nie zgadzać się z ich decyzją lub uzasadnieniem, ale to kwestia dyskusyjna.
Muszę powiedzieć, że to pytanie zostało ponownie otwarte przez wprowadzenie domyślnych metod w Javie 8. Projekt, nad którym obecnie pracuję, jest podobny do podstawowego charakteru interfejsu i ma na celu oderwanie od implementacji.
Jest kilka przypadków, w których mógłbym drastycznie uprościć mój kod za pomocą metody „domyślnej ochrony”. Okazuje się, że to w rzeczywistości nie działa, ponieważ interfejsy nadal są zgodne z logiką Java 7. Zwykła metoda chroniona nie ma większego sensu z powodów wymienionych powyżej; ale jeśli domyślna metoda publiczna wymaga zasobu niskiego poziomu, który prawdopodobnie się nie zmieni i może być dostarczony za pomocą metody chronionej, wydaje mi się, że posiadanie pracy „domyślnej chronionej” nie tylko utrzymałoby czystszy kod, ale także chroniłoby przyszłych użytkowników przed przypadkowe nadużycia.
(To tragicznie nie zmienia faktu, że nadal muszę nadmiernie komplikować swój kod niepotrzebnymi streszczeniami, ale zamierzam złożyć prośbę o funkcję w Oracle).
Zgadzam się w 100%. Klasy abstrakcyjne były rozsądną alternatywą przed wprowadzeniem metod domyślnych. Jednak ograniczenia, jakie nakładają na wielokrotne dziedziczenie, oznaczają, że nie są one doskonałe. Interfejsy z metodami domyślnymi są zwykle lepszą alternatywą w świecie> = JDK 1.8, ale ponieważ nie mogą przechowywać stanu, polegają na zdefiniowaniu innych abstrakcyjnych metod w celu ujawnienia stanu, co oznacza, że stan jest upubliczniany, co nie zawsze jest tym, czym jest chcesz.
Ks. Jeremy Krieg
10
Ponieważ interfejsy definiują publiczne interfejsy API. Wszystko, co jest chronione, jest szczegółem wewnętrznym, który nie należy do interfejsu.
Możesz używać klas abstrakcyjnych z chronionymi metodami abstrakcyjnymi, ale interfejsy są ograniczone do metod publicznych i publicznych statycznych pól końcowych.
Napisałeś „ponieważ interfejsy definiują publiczne interfejsy API”. Więc jaki jest powód, dla którego interfejsy powinny definiować tylko publicinterfejsy API? Istnieje różnica między „szczegółem wewnętrznym” a „szczegółem implementacji”, protectedw Javie zdecydowanie nie jest to szczegół wewnętrzny, ponieważ jest to teraz publiczny interfejs publikowany dla każdego, kto może go podklasować, czyli w zasadzie dla całego świata.
Pacerier,
1
Już nie jest prawdą z domyślnymi metodami Java 8.
Mario Rossi
@MarioRossi I to już nie jest prawdą z prywatnymi metodami interfejsu Java 9.
skomisa
7
Być może dlatego, że jest to interfejs , czyli po to, aby powiedzieć klientom, co mogą zrobić z instancjami, a nie powiedzieć im, czego nie mogą zrobić.
Nie rozumiem, dlaczego interfejs nie mógł również powiedzieć podklasom, co mogą zrobić bez ujawniania tej implementacji światu zewnętrznemu. To była decyzja projektowa, która została podjęta w czasie, gdy klasy abstrakcyjne mogły być używane jako doskonała alternatywa. Jednak wraz z pojawieniem się domyślnych metod w interfejsach, klasy abstrakcyjne są teraz niedoskonałą alternatywą.
Ks. Jeremy Krieg
6
Jestem głęboko przekonany , że interfejsy powinny umożliwiać metody chronione; kto powiedział, że interfejsy muszą być widoczne dla wszystkich na całym świecie? Jeśli chodzi o twój punkt widzenia, może to zmylić "zwykłych" (czytaj: niekompetentnych) programistów: tak wiele z OOP dotyczy właściwej struktury obiektów, klas, pakietów itp., Jeśli programista ma trudności z wykonaniem tego wszystkiego poprawnie, ma dużo większy problem. Java została stworzona do tego typu rzeczy.
W kilku odpowiedziach stosuje się rozumowanie cykliczne, aby wyjaśnić, dlaczego metody interfejsu nie mogą być chronione: to dlatego, że muszą być publiczne, więc oczywiście nie można ich chronić!
Metody chronione w interfejsach: udostępnianie w pakietach
Ponieważ modyfikatory są nieco ograniczone w Javie, sposób udostępniania metod w pakietach jest ograniczony do metod publicznych. Czasami upublicznienie metody jest niebezpieczne, ale musi to być spowodowane brakiem odpowiednich modyfikatorów. Moje rozwiązanie pokonuje to ograniczenie.
Specyfikacja języka Java nie zezwala obecnie na chroniony modyfikator metod interfejsu. Możemy wykorzystać ten fakt i zastosować chronione metody interfejsu dla tej nowej funkcji.
Jeśli metoda interfejsu jest oznaczona jako chroniona, a interfejs jest implementowany przez klasę w innym pakiecie, metoda nie musiałaby być publiczna, ale mogłaby być również prywatna lub przynajmniej chroniona pakietem. Metoda jest widoczna, jakakolwiek klasa deklaruje ją jako i dodatkowo widoczna w pakiecie źródłowym interfejsu (i pakietach podrzędnych?).
W ten sposób moglibyśmy udostępniać pewne metody w dobrze znanych pakietach.
A oto odpowiedź na to żądanie ulepszenia, które zostało zamknięte ze statusem Won't fix:
Ta propozycja jest próbą rozwiązania problemu w sposób, który zwiększa złożoność i powoduje szczególne przypadki, przy niewielkich korzyściach. Typowym sposobem rozwiązania tego problemu jest posiadanie klasy prywatnej, która implementuje interfejs publiczny. Metody implementacji są publiczne, ale znajdują się w klasie prywatnej, więc pozostają prywatne.
Alternatywą dostępną począwszy od Java 9 jest upublicznienie klas i metod, ale w module, który ma kwalifikowany eksport do określonych modułów „zaprzyjaźnionych”, zamiast być eksportowanym do ogółu społeczeństwa.
Tak więc autorytatywne wnioski z tego raportu o błędzie to:
Obecna sytuacja nie ulegnie zmianie; interfejsy prawdopodobnie nigdy nie będą obsługiwać protectedmetod.
Uzasadnieniem dla braku obsługi protectedmetod w interfejsach jest to, że „ zwiększa złożoność i specjalne przypadki dla niewielkiego rzeczywistego zysku ”.
Od wersji Java 9 istnieje alternatywne podejście do zapewniania dostępu do metod na poziomie pakietu. Użyj Java Platform Module System (JPMS), aby „ upublicznić klasy i metody, ale w module, który ma kwalifikowany eksport do określonych modułów„ zaprzyjaźnionych ”, zamiast być eksportowanym do ogółu społeczeństwa ”.
Ponieważ klasa implementująca musi implementować WSZYSTKIE metody zadeklarowane w Twoim interfejsie, co by się stało, gdyby klasa implementująca znajdowała się w innym pakiecie?
Interfejs Jeśli chcesz użyć czegoś takiego, jak opisałeś, kontynuuj z klasami abstrakcyjnymi lub zagnieżdżonymi interfejsami.
Fragment ze stylu kodu o zmiennych interfejsowych, ale nadal ma zastosowanie do metod:
Zmienne interfejsu są niejawnie publiczne, ponieważ interfejsy mają zapewniać interfejs programowania aplikacji (API), który jest w pełni dostępny dla programistów języka Java do odwoływania się i implementacji we własnych aplikacjach. Ponieważ interfejs może być używany w pakietach Java, które różnią się od ich własnych, publiczna widoczność zapewnia, że kod programu ma dostęp do zmiennej.
Deklarowanie wewnętrznych podinterfejsów jest dobrą praktyką, ale technicznie nie można deklarować swoich metod wewnętrznych, tak jak protectedw interfejsie w Javie.
Oczywiście możesz stworzyć inny interfejs do użytku wewnętrznego, który rozszerza interfejs publiczny:
Możesz użyć InternalInterfaceinterfejsu wewnątrz pakietu, ale powinieneś zaakceptować dowolny podtyp PublicInterface(w metodach publicznych):
package yourpackage;publicclassSomeClass{publicvoid someMethod(PublicInterface param){if(param instanceofInternalInterface){// run the optimized code}else{// run the general code}}}
Poza pakietem użytkownicy mogą korzystać PublicInterfacebez problemów.
Zwykle programiści tworzą klasy abstrakcyjne w podobnych sytuacjach. Jednak w tym przypadku tracimy korzyści wynikające z wielokrotnego dziedziczenia.
Poza pakietem użytkownicy mogą również używać YourPublicInterface.Internal. Wszystko w interfejsie, w tym interfejsy zagnieżdżone, jest publiczne, niezależnie od obecności lub braku publicsłowa kluczowego.
Greg Roelofs
1
Jedynym scenariuszem, w którym miałoby to sens, jest ograniczenie widoczności do tego samego pakietu. Wszystkie inne zastosowania protectednie mają zastosowania. W szczególności protectedmetody są często używane w celu zapewnienia dostępu do niektórych szczegółów implementacji niższego poziomu dla potomków. Ale deklarowanie tego w interfejsie nie ma sensu, ponieważ nie ma implementacji niższego poziomu do ujawnienia.
I nawet scenariusz pakietu nie jest tak naprawdę tym, o co chodzi w interfejsach.
Aby osiągnąć to, czego prawdopodobnie chcesz, potrzebujesz dwóch interfejsów, jednego do użytku wewnętrznego i jednego, który udostępniasz w publicznym API. (Z wewnętrzną możliwie, ale niekoniecznie rozszerzającą publiczną.) Lub, jak wskazywali inni, abstrakcyjna superklasa.
Abstrakcyjna nadklasa może uniemożliwić jej wyprowadzenie przez typy spoza jej pakietu. Ktoś, kto otrzyma referencję takiego typu nadklasy i ufa autorowi pakietu, może być pewny, że obiekt będzie zachowywał się zgodnie z założeniami. Jeśli pakiet ma wiele klas, które chcą ujawnić jakąś wspólną funkcjonalność, ale nie pasują do odpowiedniej hierarchii (np. Jedna implementuje funkcje X i Y, jedna Y i Z oraz jedna X i Z), byłoby pomocne, gdyby funkcjonalność wykorzystująca interfejsy, choć wciąż obiecuje, że wystąpienia, do których odnoszą się typy interfejsów, będą „autentyczne”.
supercat
0
Metody chronione są zawsze dostępne dla podklasy tylko wtedy, gdy podklasa rozszerza klasę bazową.
W przypadku interfejsu podklasa nigdy nie rozszerza interfejsu. Implementuje interfejs.
Metody chronione są dostępne za pośrednictwem rozszerzenia, a nie narzędzia .
jaka różnica jakie słowo kluczowe, to nie ma znaczenia.
Alex78191
0
Interfejsy mają na celu ujawnienie metod światu zewnętrznemu . Zatem metody te są z natury publiczne. Jeśli jednak chcesz wprowadzić abstrakcję w ramach tej samej rodziny klas , możesz stworzyć inny poziom abstrakcji między Twoim interfejsem a klasą implementacji, czyli klasę abstrakcyjną. Przykład przedstawiono poniżej.
publicinterfaceMyInterface{publicvoid publicMethod();// needs to be public}publicabstractclassMyAbstractClassimplementsMyInterface{@Overridepublicvoid publicMethod(){
protectedMethod();// you can call protected method here// do other stuff}protectedabstractvoid protectedMethod();// can be protected}publicclassMyClassextendsMyAbstractClass{@Overrideprotectedvoid protectedMethod(){// implement protected method here, without exposing it as public}}
Jednak w interfejsach dozwolone są metody prywatne, których nikt nie zobaczy.
Alex78191
java ma domyślne metody w interfejsach, to znaczy interfejs jest podpórką do ominięcia wielokrotnego dziedziczenia klas abstrakcyjnych. Niech więc jest dozwolone wielokrotne dziedziczenie klas abstrakcyjnych. Konflikty metod domyślnych nie stały się problemem.
Alex78191
Masz rację. Od wersji Java 9 w interfejsach dozwolone są prywatne metody. Nie mogą być abstrakcyjne i są implementowane i używane w interfejsie, głównie za pomocą innych metod domyślnych lub statycznych (jeśli same są statyczne).
Stefanos Kargas
1
Ta odpowiedź po prostu ignoruje zadane pytanie: dlaczego interfejsy nie mogą mieć chronionych metod? Metody chronione nadal „ujawniałyby metody światu zewnętrznemu” , a twierdzenie, że „metody te są z natury publiczne”, jest po prostu fałszywe. Są publiczne, ponieważ język został zaprojektowany w ten sposób, ale mógł pozwolić na chronione metody w interfejsach. PO po prostu pyta dlaczego.
protected
metodę, wszystkie klasy implementujące będą postrzegane jako podtyp interfejsu. a wszystkie te klasy MOGĄ mieć dostęp do metod chronionych. czy nie powoduje to, żeprotected
słowo kluczowe w metodzie jest bezużyteczne? o ile nie mamy możliwości ograniczenia, kto implementuje ten interfejs, chronione słowo kluczowe w metodzie jest bezużyteczne. Popraw mnie, jeśli się mylę!Odpowiedzi:
Ponieważ interfejs ma oznaczać „to, co widać spoza klasy”. Nie ma sensu dodawać metod niepublicznych.
źródło
abstract class
, co jest winterface
porządku, i określić dowolny dostęp. Przyznane to traci korzyści z wielu implementacji, któreinterface
są dostępne w Javie, ale uczciwe ustanowienie kontraktu, który jest zgodny z ograniczeniami jakiegoś innego pakietu, byłoby niesprawdzalne i mylące, ponieważ praktycznie nie byłbyś w stanie uzyskać dostępu do metody własnej implementacji poza tym pakietem .Chociaż często przytaczanym powodem jest to, że „interfejsy definiują publiczne API”, myślę, że jest to nadmierne uproszczenie. (I "pachnie" też logiką kolistą.)
Nie byłoby bez sensu posiadanie interfejsów zawierających mieszankę modyfikatorów dostępu; np. częściowo publiczne, a częściowo ograniczone do innych klas w tym samym pakiecie co interfejs. W rzeczywistości w niektórych przypadkach może to być przydatne w dół, IMO.
Właściwie uważam, że częścią rozumowania stojącego za upublicznieniem elementów interfejsu jest to, że upraszcza to język Java :
Niejawnie publiczne elementy składowe interfejsu są prostsze w obsłudze dla programistów. Ile razy widziałeś kod (klasy), w którym modyfikatory dostępu do metody były wybierane pozornie losowo? Wielu „zwykłych” programistów ma trudności ze zrozumieniem, jak najlepiej zarządzać granicami abstrakcji Javy 1 . Dodanie publicznego / chronionego / prywatnego pakietu do interfejsów sprawia, że jest to jeszcze trudniejsze.
Niejawnie publiczne elementy interfejsu upraszczają specyfikację języka ... a tym samym zadanie dla autorów kompilatorów Java i osób, które implementują interfejsy API Reflection.
Myślenie, że „interfejsy definiują publiczne API” jest prawdopodobnie konsekwencją (lub cechą) decyzji dotyczącej projektu uproszczenia języka ... a nie na odwrót. Ale w rzeczywistości te dwa nurty myślenia prawdopodobnie rozwinęły się równolegle w umysłach projektantów Javy.
W każdym razie oficjalna odpowiedź na RFE w JDK-8179193 jasno pokazuje, że zespół projektowy Java zdecydował 2, że dopuszczenie
protected
interfejsów zwiększa złożoność i przynosi niewielkie realne korzyści. Uznanie dla @skomisa za znalezienie dowodów .Dowody w RFE rozwiązują problem. To jest oficjalny powód, dla którego nie został dodany.
1 - Oczywiście programiści z najwyższej półki nie mają z tym trudności i mogą z zadowoleniem przyjąć bogatszą paletę funkcji kontroli dostępu. Ale co się stanie, gdy ich kod zostanie przekazany komuś innemu w celu utrzymania?
2 - Możesz nie zgadzać się z ich decyzją lub uzasadnieniem, ale to kwestia dyskusyjna.
źródło
Muszę powiedzieć, że to pytanie zostało ponownie otwarte przez wprowadzenie domyślnych metod w Javie 8. Projekt, nad którym obecnie pracuję, jest podobny do podstawowego charakteru interfejsu i ma na celu oderwanie od implementacji.
Jest kilka przypadków, w których mógłbym drastycznie uprościć mój kod za pomocą metody „domyślnej ochrony”. Okazuje się, że to w rzeczywistości nie działa, ponieważ interfejsy nadal są zgodne z logiką Java 7. Zwykła metoda chroniona nie ma większego sensu z powodów wymienionych powyżej; ale jeśli domyślna metoda publiczna wymaga zasobu niskiego poziomu, który prawdopodobnie się nie zmieni i może być dostarczony za pomocą metody chronionej, wydaje mi się, że posiadanie pracy „domyślnej chronionej” nie tylko utrzymałoby czystszy kod, ale także chroniłoby przyszłych użytkowników przed przypadkowe nadużycia.
(To tragicznie nie zmienia faktu, że nadal muszę nadmiernie komplikować swój kod niepotrzebnymi streszczeniami, ale zamierzam złożyć prośbę o funkcję w Oracle).
źródło
Ponieważ interfejsy definiują publiczne interfejsy API. Wszystko, co jest chronione, jest szczegółem wewnętrznym, który nie należy do interfejsu.
Możesz używać klas abstrakcyjnych z chronionymi metodami abstrakcyjnymi, ale interfejsy są ograniczone do metod publicznych i publicznych statycznych pól końcowych.
źródło
public
interfejsy API? Istnieje różnica między „szczegółem wewnętrznym” a „szczegółem implementacji”,protected
w Javie zdecydowanie nie jest to szczegół wewnętrzny, ponieważ jest to teraz publiczny interfejs publikowany dla każdego, kto może go podklasować, czyli w zasadzie dla całego świata.Być może dlatego, że jest to interfejs , czyli po to, aby powiedzieć klientom, co mogą zrobić z instancjami, a nie powiedzieć im, czego nie mogą zrobić.
źródło
Jestem głęboko przekonany , że interfejsy powinny umożliwiać metody chronione; kto powiedział, że interfejsy muszą być widoczne dla wszystkich na całym świecie? Jeśli chodzi o twój punkt widzenia, może to zmylić "zwykłych" (czytaj: niekompetentnych) programistów: tak wiele z OOP dotyczy właściwej struktury obiektów, klas, pakietów itp., Jeśli programista ma trudności z wykonaniem tego wszystkiego poprawnie, ma dużo większy problem. Java została stworzona do tego typu rzeczy.
źródło
W kilku odpowiedziach stosuje się rozumowanie cykliczne, aby wyjaśnić, dlaczego metody interfejsu nie mogą być chronione: to dlatego, że muszą być publiczne, więc oczywiście nie można ich chronić!
To nic nie wyjaśnia, ale na szczęście ktoś kilka lat temu zgłosił prośbę o ulepszenie metod chronionych w interfejsach jako błąd JDK , co rzuca trochę światła na problem:
A oto odpowiedź na to żądanie ulepszenia, które zostało zamknięte ze statusem
Won't fix
:Tak więc autorytatywne wnioski z tego raportu o błędzie to:
protected
metod.protected
metod w interfejsach jest to, że „ zwiększa złożoność i specjalne przypadki dla niewielkiego rzeczywistego zysku ”.źródło
Ponieważ klasa implementująca musi implementować WSZYSTKIE metody zadeklarowane w Twoim interfejsie, co by się stało, gdyby klasa implementująca znajdowała się w innym pakiecie?
źródło
Interfejs Jeśli chcesz użyć czegoś takiego, jak opisałeś, kontynuuj z klasami abstrakcyjnymi lub zagnieżdżonymi interfejsami.
Fragment ze stylu kodu o zmiennych interfejsowych, ale nadal ma zastosowanie do metod:
źródło
Deklarowanie wewnętrznych podinterfejsów jest dobrą praktyką, ale technicznie nie można deklarować swoich metod wewnętrznych, tak jak
protected
w interfejsie w Javie.Oczywiście możesz stworzyć inny interfejs do użytku wewnętrznego, który rozszerza interfejs publiczny:
Możesz użyć
InternalInterface
interfejsu wewnątrz pakietu, ale powinieneś zaakceptować dowolny podtypPublicInterface
(w metodach publicznych):Poza pakietem użytkownicy mogą korzystać
PublicInterface
bez problemów.Zwykle programiści tworzą klasy abstrakcyjne w podobnych sytuacjach. Jednak w tym przypadku tracimy korzyści wynikające z wielokrotnego dziedziczenia.
źródło
YourPublicInterface.Internal
. Wszystko w interfejsie, w tym interfejsy zagnieżdżone, jest publiczne, niezależnie od obecności lub brakupublic
słowa kluczowego.Jedynym scenariuszem, w którym miałoby to sens, jest ograniczenie widoczności do tego samego pakietu. Wszystkie inne zastosowania
protected
nie mają zastosowania. W szczególnościprotected
metody są często używane w celu zapewnienia dostępu do niektórych szczegółów implementacji niższego poziomu dla potomków. Ale deklarowanie tego w interfejsie nie ma sensu, ponieważ nie ma implementacji niższego poziomu do ujawnienia.I nawet scenariusz pakietu nie jest tak naprawdę tym, o co chodzi w interfejsach.
Aby osiągnąć to, czego prawdopodobnie chcesz, potrzebujesz dwóch interfejsów, jednego do użytku wewnętrznego i jednego, który udostępniasz w publicznym API. (Z wewnętrzną możliwie, ale niekoniecznie rozszerzającą publiczną.) Lub, jak wskazywali inni, abstrakcyjna superklasa.
źródło
Metody chronione są zawsze dostępne dla podklasy tylko wtedy, gdy podklasa rozszerza klasę bazową.
W przypadku interfejsu podklasa nigdy nie rozszerza interfejsu. Implementuje interfejs.
Metody chronione są dostępne za pośrednictwem rozszerzenia, a nie narzędzia .
źródło
Interfejsy mają na celu ujawnienie metod światu zewnętrznemu . Zatem metody te są z natury publiczne. Jeśli jednak chcesz wprowadzić abstrakcję w ramach tej samej rodziny klas , możesz stworzyć inny poziom abstrakcji między Twoim interfejsem a klasą implementacji, czyli klasę abstrakcyjną. Przykład przedstawiono poniżej.
źródło