2011-11-03 14 views
19

tj. dlaczego nie jest możliwa następująca "zależność cykliczna"?Dlaczego Java zabrania dziedziczenia wewnętrznych interfejsów?

public class Something implements Behavior { 
    public interface Behavior { 
     // ... 
    } 
} 

Ponieważ interfejsy nie odwołują się do klasy zewnętrznej, powinno to być dozwolone; jednak kompilator zmusza mnie do zdefiniowania tych interfejsów poza klasą. Czy istnieje jakieś logiczne wytłumaczenie tego zachowania?

+0

Brzmi tak, jakby program ładujący klasy musiał najpierw przeczytać klasę, aby poznać interfejs, który musi zdefiniować klasę ... Nie znam szczegółów ładowania klasowego, ale wydaje się to dość oczywiste. –

+2

@donneo: ponieważ kompilator narzeka na "cykliczną zależność", wyobrażam sobie, że już wie, które typy są zdefiniowane w wewnętrznej klasie. Po prostu wydaje mi się to arbitralnym ograniczeniem. –

+0

@PhilipK: jakiego używasz kompilatora? Mój (Oracle JDK 6 i 7) tylko narzeka, że ​​"nie może znaleźć symbolu". Poza tym: dobre pytanie, ponieważ zagnieżdżony interfejs tak naprawdę nie polega * na zewnętrznej klasie w żaden techniczny sposób, to * może * być legalne. –

Odpowiedz

11

odpowiednich zasad w specyfikacji:

http://java.sun.com/docs/books/jls/third_edition/html/classes.html#8.1.4

klasy C bezpośrednio zależy od typu T, jeżeli T wskazanego na wydłuża się lub wprowadza klauzuli C albo jako nadrzędnej lub superinterface lub jako kwalifikator nazwy superklasy lub superinterfejsu.

http://java.sun.com/docs/books/jls/third_edition/html/interfaces.html#9.1.3

interfejs i bezpośrednio zależy od typu T, gdy T jest wymienione w rozciąga klauzuli I albo jako superinterface lub eliminacji w nazwie superinterface.

Dlatego jeśli A extends|implements B.C A zależy zarówno C i B. Spec wtedy zabrania kołowych zależności.

Motywacja włączenia B do zależności jest niejasna. Jak już wspomniałeś, jeśli B.C jest promowany do najwyższego poziomu C2, niewiele się różni w odniesieniu do systemu typów, więc dlaczego A extends C2 jest ok, ale nie A extends B.C?Przyznany typ zagnieżdżony B.C ma pewien prviledged dostęp do zawartości B, ale nie mogę znaleźć niczego w specyfikacji, która sprawia, że ​​A extends B.C kłopotliwe.

Jedynym problemem jest sytuacja, gdy C jest wewnętrzną klasą. Przypuśćmy, że powinno być zabronione: B=A, A extends A.C, ponieważ istnieje okrężna zależność "załączającej instancji". Jest to prawdopodobnie prawdziwa motywacja - zakazanie zewnętrznej klasy dziedziczeniu wewnętrznej klasy. Rzeczywiste reguły są bardziej uogólnione, ponieważ są prostsze i mają sens nawet w przypadku klas innych niż wewnętrzne.

10

Wyobraź sobie, że jesteś kompilatorem.

Mówimy Ci, aby stworzyć klasę Coś. Ta klasa implementuje zachowanie ... Ale zachowanie jeszcze nie istnieje, ponieważ coś jeszcze nie jest zarejestrowane ...

Czy rozumiesz problem?

Zobacz klasę jako pudełko, które zawiera rzeczy. Zachowanie jest zawarte w polu Coś. Ale Coś nie istnieje.

+3

To byłaby poprawna odpowiedź, gdyby pytanie dotyczyło języka C++. –

+1

Tak, ale Zachowanie jest interfejsem i dlatego nie zależy od stworzenia Coś. –

+0

Tak, ponieważ ten interfejs jest częścią Coś. Coś musi istnieć, zanim będziesz mógł odwołać się do Zachowania, ale stworzyć Coś, czego potrzebujesz do odniesienia się do Zachowania. –

0

Prosty fakt, że specyfikacja językowa zabrania, powinna wystarczyć.

Niektóre przyczyny mogłem pomyśleć:

  • Nie byłoby użyteczne.

  • Z dowolnych powodów, z których możesz skorzystać, jestem pewien, że istnieją lepsze opcje.

  • Zajęcia dla dzieci powinny rozszerzać klasy bazowe, dlaczego więc zadeklarowałbyś klasę bazową w swoim własnym dziecku?

  • Byłoby sprzeczne z intuicją, gdyby oddzielna klasa rozszerzyła twoją wewnętrzną klasę.

+0

Przydałoby się to w przypadkach, w których potrzebujemy interfejsu wywołania zwrotnego, aby przejść do innej klasy. – ismailarilik

Powiązane problemy