2011-08-23 14 views
10

Dobra, wiem, że to reguła:Dlaczego interfejs można deklarować tylko w klasie najwyższego poziomu?

Według JLS: 8.1.3 Klasy wewnętrzne i załączając przypadkach wewnętrzne klasy nie może zadeklarować inicjatorów statyczne lub interfejsy członków. Klasy wewnętrzne mogą nie zadeklarować statycznych elementów, chyba że są stałymi polami stałej kompilacji.

Według 8.5.2 Statyczny element członkowski typu deklaracji, „interfejsy użytkownika zawsze są domyślnie statyczne. Jest to dozwolone, ale nie wymagane dla deklaracji z interfejsem użytkownik jawnie notować statycznego modyfikator”. Są zawsze na najwyższym poziomie, a nie wewnętrznie.

Po prostu zastanawiam się, dlaczego. Co może się zdarzyć, jeśli możemy zadeklarować interfejs wewnątrz wewnętrznej klasy? Czy klasa wewnętrzna nie stanie się klasą najwyższego poziomu, jeśli umieści się ją w innym pliku klasy?

Odpowiedz

7

Czy klasa wewnętrzna nie stanie się klasą najwyższego poziomu, jeśli umieści się ją w innym pliku klasy?

Nie, nadal jest klasą wewnętrzną, która wskazuje nazwę pliku (IIRC to OuterClass$InnerClass.class).

Klasy wewnętrzne mają dostęp do atrybutów klasy zewnętrznej, tj. Zależą od ich klasy zewnętrznej. Z interfejsami nie można tego zrobić. Pomyśl o zupełnie niepowiązanej klasie, która musiałaby zostać stworzona przez odpowiadającą jej instancję klasy zewnętrznej. Jak to zrobić, jeśli klasa zewnętrzna nie wie, kto implementuje ten interfejs?

Co można zrobić, to zadeklarować interfejsów statycznych w swojej zewnętrznej klasy, tak więc jedynie za pomocą zewnętrznego jako nazw:

public class OuterClass { 
    public static interface InnerInterface { //protected and private would be fine too, depending on what makes sense 
    } 
} 

Edycja: faktycznie, ja misread pytanie, a ponieważ interfejsy są statyczne czy inaczej, oto zaktualizowany fragment kodu:

public class OuterClass { 
    public static InnerClass { //static inner class making OuterClass just be a namespace 
    public interface InnerInnerInterface { //protected and private would be fine too, depending on what makes sense 
    } 
    } 
} 

Jako obejście można zdefiniować abstrakcyjną klasę wewnętrzną wewnętrzny, z taką wadę, że trzeba trzymać się pojedynczego dziedziczenia ograniczeń.

+0

Hmm, ciekawe! Nigdy nie wiem, że interfejs można zadeklarować jako statyczny. Co oznacza tutaj "statyczny"? Próbowałem już interfejsu statycznego Google, ale niczego nie odkryłem. P/s: Po prostu edytuj mój post w cytowanej linii, aby poprawić błąd gramatyki. –

+2

@ W.N .: Interfejsy są niejawnie statyczne. Ta deklaracja jest po prostu rewolucyjna. –

+1

@Ryan dobry punkt, ja też po prostu ponownie przeczytałem pytanie i zaktualizuję moją odpowiedź. – Thomas

1

Klasy wewnętrzne mają być szczegółami implementacji klasy najwyższego poziomu i dlatego powinny być niewidoczne dla klienta. Każda funkcjonalność, do której chcesz uzyskać dostęp do klasy wewnętrznej, powinna być wykonana przez klasę najwyższego poziomu, ponieważ koncepcyjnie rzecz biorąc, ta funkcjonalność powinna być widoczna tylko jako funkcjonalność klasy najwyższego poziomu, aby projektant klasy mógł zamienić lub w inny sposób drastycznie zmieniaj klasy wewnętrzne bez łamania kompilacji klientów.

+2

To wszystko jest kwestia opinii. Jeśli klasy wewnętrzne byłyby przeznaczone tylko do użytku wewnętrznego klasy nadrzędnej, nie pozwoliłoby się na ich "publiczne". – skaffman

2

Z definicji klasa najwyższego poziomu i jej klasa wewnętrzna są ściśle powiązane. Interfejsy są sposobem zmniejszenia sprzężenia.

+1

Nawet jeśli muszę prywatnie używać tego interfejsu dla wewnętrznej klasy? –

+0

To niekoniecznie dobry argument, ponieważ napisałem kilka prywatnych, zagnieżdżonych interfejsów, które są używane tylko w ramach jednej klasy. –

4

Pomyśl o tym w kategoriach kontekstu statycznego i nie statycznego. Klasa "najwyższego poziomu" ustanawia kontekst statyczny, ponieważ można uzyskać do niej dostęp bez żadnej załączającej instancji. To znaczy. możesz uzyskać dostęp do klas najwyższego poziomu z głównej metody. To samo dotyczy wszystkich statycznych członków klasy najwyższego poziomu. Klasa wewnętrzna jednak nie istnieje w * ani nie ustanawia żadnego statycznego kontekstu. Dlatego nie może mieć żadnych statycznych elementów, a dostęp do niego można uzyskać tylko za pośrednictwem instancji swojej klasy zawierającej, na przykład konstruktorów i innych elementów instancji. Z głównej metody nie można powiedzieć Outer.Inner.SOME_FIELD, ponieważ członkowie klasy wewnętrznej mają znaczenie tylko w odniesieniu do klasy zawierającej.

* sortowanie

+0

Ta odpowiedź sprawi, że odpowiedź Thomasa będzie jaśniejsza. +1. –

Powiązane problemy