即,爲什麼下面的「循環依賴」不可能?Java爲什麼禁止繼承內部接口?
public class Something implements Behavior {
public interface Behavior {
// ...
}
}
由於接口不引用外部類,所以應該允許;然而,編譯器迫使我在類之外定義這些接口。這種行爲有沒有合理的解釋?
即,爲什麼下面的「循環依賴」不可能?Java爲什麼禁止繼承內部接口?
public class Something implements Behavior {
public interface Behavior {
// ...
}
}
由於接口不引用外部類,所以應該允許;然而,編譯器迫使我在類之外定義這些接口。這種行爲有沒有合理的解釋?
相關規則:
http://java.sun.com/docs/books/jls/third_edition/html/classes.html#8.1.4
甲類,如果提到T IN的延伸或實現的C子句無論是作爲一個超類或超Ç直接取決於類型T ,或作爲超類或超接口名稱的限定符。
http://java.sun.com/docs/books/jls/third_edition/html/interfaces.html#9.1.3
如果T在被提及的延伸予任一條款作爲超接口或作爲超接口名稱中的限定符我直接依賴於一個T型的接口。
因此,如果A extends|implements B.C
,A同時取決於C
和B
。 Spec然後禁止循環依賴。
在依賴中包含B
的動機尚不清楚。正如你所提到的,如果B.C
被提升到頂級C2
,就類型系統而言並沒有太大的不同,那麼爲什麼A extends C2
沒問題,而不是A extends B.C
?授予一個嵌套類型B.C
確實有一些progragedged訪問B
的內容,但我找不到任何規格,使A extends B.C
麻煩。
唯一的問題是當C
是一個內部類。假設B=A
,A extends A.C
應該被禁止,因爲有「封閉實例」的循環依賴。這可能是真正的動機 - 禁止外部類繼承內部類。實際的規則是更普遍的,因爲它們更簡單,並且即使對於非內部類也是很有意義的。
想象一下,你是編譯器。
我們說你要創建一個類的東西。 此課程實施行爲... 但行爲尚不存在,因爲有些東西尚未註冊...
您是否瞭解該問題?
查看類包含東西的框。行爲包含在框中的東西。但有些東西不存在。
如果問題是關於C++的話,這將是一個有效的答案。 –
是的,但行爲是一個接口,因此不依賴於創建的東西。 –
是的,因爲該界面是Something的一部分。在引用行爲之前需要存在某些東西,但要創建需要引用行爲的東西。 –
一個簡單的事實,即語言規範禁止它應該是足夠的。
我能想到的一些原因:
它不會是有用的。
無論出於什麼原因,你可能想要使用這個,我相信有更好的選擇。
子類應該擴展基類,那麼爲什麼要在自己的子類中聲明一個基類?
這將是反直覺有一個單獨的類擴展你的內部類。在規範
這對於我們需要回調接口傳遞給不同類的情況很有用。 – ismailarilik
類似於類加載器的聲音必須首先閱讀該類才能知道它需要首先定義類的接口......我不知道類加載的細節,但看起來很明顯。 –
@donneo:由於編譯器抱怨「循環依賴」,我想它已經知道內部類中定義了哪些類型。這對我來說似乎是一種任意的限制。 –
@PhilipK:你在用什麼編譯器?我的(Oracle JDK 6和7)只會抱怨他們「找不到符號」。除此之外:很好的問題,因爲嵌套接口不以任何技術方式真正依賴外部類,這*可能是合法的。 –