2017-09-07 6 views
1

2つのクラスが互いにサブクラス化するとどうなるのだろうと思っていました。私はIntelliJ IDEAを使ってScalaで試してみました。実装にはエラーはありませんが、testオブジェクト内の行のコメントを外すと、IDEがフリーズして、私は何もできません。ここで実際に何が起こっていますか?2つのクラスが互いにサブクラス化すると、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コンパイラがあると思いますが、おそらくバグでしょうか? –

+0

@ insan-eうん、そうだね。私はアプリケーションを実行する必要はないと考えてかなり危険だと思って、それを入力するだけでIntelliJがフリーズしました –

答えて

2

IDEのバージョンが早期にエラーを識別および/またはスコープ内のオートコンプリートの提案を提供するために、あなたのコードのクラス構造を解決しようとしているように思えます。しかし、再帰的なサブクラスを追跡/停止する条件はないようです。

最新のバージョンに更新してください。それでも問題が解決しない場合は、バグレポートを提出してください。それまでは、IDEで無効にできる設定があるため、循環クラスの依存関係を解決しようとするとフリーズしません。オートコンプリートの設定を変更すると、訂正や提案の正確性が失われるか完全に無効になることがありますが、コードを実行/コンパイルしてエラー(循環的なクラスの依存関係)を特定して修正することができます。


循環的なクラスの依存関係は、複数のクラスがループ内で互いに継承する場合です。我々は二つのクラス、class Aclass Bを持っている場合は、この擬似コードに示すように、例えば、我々は循環依存関係ループを作成することができます。

class A inherits B; 
class B inherits A; 

多くのコンパイラやインタプリタはこれを評価すると、彼らは最初の行を参照してロードしようBBをロードするには、行2の宣言に進みます。次に、Aをロードする必要があることがわかります。ここではスマートなコンパイラまたはインタプリタはテーブルを反転させますが、それは既に試してみてAの読み込みに失敗したためです。素朴な人が幸せに指示に従います。

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

賢いコンパイラやインタプリタは、実際に円クラスの依存関係をロードして動作するコードを作成することができます。しかし、これらは非常にまれです。プログラマとしては、この能力を持たない言語で循環クラスの依存関係を持つことが絶対に不可欠です。

これはクラス構成のアイデアが入っている場所です。スーパークラスを継承するのではなく、Bの作業コピーをクラスAに変数として渡すことができます。

場合によっては、BがクラスAになることを可能にする変換機能を提供することもできます。彼らがお互いに継承している場合、彼らの行動が違うにもかかわらず、同じデータを含んでいる可能性が非常に高いです!一部の言語には、この変換を行う機能が組み込まれています。最も単純な例は「タイプキャスト」です。いくつかの言語では、この変換をパラメトリック多型に一般化しています。互換性のある型を最初に変換する必要なく機能する関数を記述することができます。


コードを難解に解析することは、コンパイラやインタープリタのバグを検出するのに最適です。だから、このスニペットを覚えておいてください。

このようなものは、バグではなく、未定義ビヘイビアとみなされます。依存しているコードで未定義の動作を混乱させたくありません。

+1

'A'に' B'型のフィールドやメソッドやローカル変数を持たせると、依存関係が作成され、継承と同様に 'B'をロードする必要があります。だから問題があった場合、 'class Shoe(val t:Table)' + 'class Table(val s:Shoe)'はどちらも動作しません。この種の循環依存性に対処できるコンパイラはまれではなく、非常にまれにしかありません。 –

+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 { 
       ^
関連する問題