2017-09-07 66 views
1

我想知道如果兩個類彼此繼承,會發生什麼,我使用IntelliJ IDEA與Scala一起試用了它。這個實現沒有任何錯誤,但是當我取消註釋test對象內部的行時,IDE就凍結了,我無能爲力。這裏真的發生了什麼?爲什麼當兩個類彼此分類時,intelliJ會凍結?

class Shoe extends Table { 

} 

class Table extends Shoe { 

} 

object test { 
    // val shoe = new Shoe() 
} 
+1

閱讀了嗎? http://www.geekinterview.com/question_details/85345 – jwpfox

+0

ScalaFiddle說「錯誤:涉及類鞋的非法循環引用」。我認爲IntelliJ有自己的Scala編譯器,可能是一個bug? –

+0

@ insan -e嗯,我想是的。相當危險,考慮到我甚至不需要運行應用程序,只是輸入那個導致IntelliJ凍結 –

回答

2

好像你的IDE版本試圖解析代碼的類結構,以儘早識別錯誤和/或提供在範圍內自動完成建議。但它似乎沒有停止跟蹤/識別遞歸子類的條件。

請務必更新至最新版本,如果不能解決此問題,請提交錯誤報告。在此之前,可能有一個設置可以在IDE中禁用,因此它不會凍結嘗試解析循環類依賴項。更正自動填充設置時,更正和建議可能會失去一些準確性或被完全禁用,但它可以讓您運行/編譯代碼以識別錯誤(循環類依賴)並對其進行修復。


循環類依賴是當多個類在循環中從eachother繼承時。例如,如果我們有兩個班,class Aclass B,我們可以創建一個循環依賴循環如本僞代碼:

class A inherits B; 
class B inherits A; 

當很多編譯或解釋評價這一點,他們看到的第一線,並嘗試加載B。要加載B,他們在第2行進行聲明。然後他們看到需要加載A。在這裏,智能編譯器或解釋器會翻轉一個表格,因爲它已經知道它已經嘗試過並且未能加載A。一個天真的人會高興地按照指示。

load B! 
load A! 
load B! 
load A! 
load B! 
load A! 

最聰明的編譯器和解釋實際上可以加載一個圓形類的依賴,並創建一個運行的代碼。但這些非常罕見。作爲一名程序員,有時在沒有這種能力的語言中有一個循環的類依賴關係是非常重要的。

這是類構圖的想法出現的地方。您可以將B的工作副本以變量的形式提供給A類,而不是繼承超類。

在某些情況下的另一個很好的選擇是提供轉換功能,允許B成爲類A;如果它們都從彼此繼承,儘管它們有不同的行爲,它們很可能包含相同的數據!有些語言具有內置的功能來執行此轉換。最簡單的例子是「類型轉換」。有些語言也將這種轉換概括爲參數多態,您可以在其中編寫一個函數,該函數可以在任何兼容類型上工作,而無需先轉換它們。


引入一個難以解析的代碼總是在編譯器和解釋器中捕獲錯誤的好方法。因此,當你必須編寫和測試一個時,請記住這個片段!

在某些語言中,像這樣的東西是,而不是一個錯誤,被認爲是未定義的行爲。您不想在任何您將依賴的代碼中混淆未定義行爲。

+1

在A中有'B'類型的字段或方法或局部變量會產生依賴關係,並且需要像繼承一樣加載'B'。所以,如果這是問題,'類鞋(val t:Table)'+'class Table(val s:鞋)'也不會起作用,但它確實如此。可以處理這種循環依賴的編譯器並不罕見,更不用說「非常罕見」。 –

+0

@AlexeyRomanov足夠。我將來會使用更具體的例子,以便我的陳述更準確。至少對於這個答案,廣泛的概述似乎足以涵蓋這個問題。這將是幾天前,我可以自由回顧這個問題,以改善這個答案,所以請隨時修改或更正我可能錯過的細節。感謝您的建設性反饋 – Aaron3468

1

沒什麼,編譯器會拒絕這樣的代碼:

scala> :paste 
// Entering paste mode (ctrl-D to finish) 

class Shoe extends Table {} 
class Table extends Shoe {} 

// Exiting paste mode, now interpreting. 

<pastie>:15: error: illegal cyclic reference involving class Shoe 
     class Table extends Shoe { 
       ^