简体   繁体   English

当两个类相互子类化时,为什么intelliJ会冻结?

[英]Why does intelliJ freeze when two classes subclasses each other?

I was wondering what will happen if two classes subclass one another, and I tried it out with Scala using IntelliJ IDEA. 我想知道如果两个类彼此子类化将会发生什么,并且我使用IntelliJ IDEA使用Scala尝试了它。 The implementation have no errors, but the minute I uncomment out the line inside the test object, the IDE just freezes up and theres nothing I can do. 实现没有错误,但是当我在test对象内部取消注释时,IDE就会冻结,而我无能为力。 What is really happening here? 这里到底发生了什么?

class Shoe extends Table {

}

class Table extends Shoe {

}

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

Seems like your version of the IDE is trying to resolve the class structure of your code to identify errors early and/or provide in-scope autocomplete suggestions. 看起来您的IDE版本正在尝试解析代码的类结构以及早识别错误和/或提供范围内的自动完成建议。 But it doesn't seem to have a condition to stop following/identify a recursive subclass. 但它似乎没有条件停止跟踪/识别递归子类。

Make sure to update to the latest version and if that doesn't fix this, file a bug report. 确保更新到最新版本,如果不能解决此问题,请提交错误报告。 Until then, there is probably a setting you can disable in the IDE so it won't freeze trying to resolve the circular class dependency. 在此之前,可能有一个设置可以在IDE中禁用,因此它不会冻结尝试解决循环类依赖关系。 Corrections and suggestions may lose some accuracy or be completely disabled when you change the autocomplete settings, but it will allow you to run/compile the code to identify the error (a cyclical class dependency) and fix it. 更改自动完成设置时,更正和建议可能会失去一些准确性或完全禁用,但它将允许您运行/编译代码以识别错误(循环类依赖关系)并修复它。


A cyclical class dependency is when multiple classes inherit from eachother in a loop. 循环类依赖是指多个类在循环中从彼此继承。 For example, if we have two classes, class A and class B , we can create a circular dependency loop as shown in this pseudocode: 例如,如果我们有两个类, class Aclass B ,我们可以创建一个循环依赖循环,如下面的伪代码所示:

class A inherits B;
class B inherits A;

When many compilers or interpreters evaluate this, they see the first line and try to load B . 当许多编译器或解释器对此进行评估时,他们会看到第一行并尝试加载B To load B , they go to its declaration in line 2. Then they see that A needs to be loaded. 为了加载B ,他们转到第2行的声明。然后他们看到A需要加载。 Here, a smart compiler or interpreter will flip a table because it already knows it tried and failed to load A . 在这里,智能编译器或解释器将翻转表,因为它已经知道它已经尝试并且无法加载A A naive one will happily follow the instructions. 一个天真的人会很乐意遵循指示。

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

The smartest compilers and interpreters actually can load a circular class dependency and create code that works. 最聪明的编译器和解释器实际上可以加载循环类依赖项并创建有效的代码。 But these ones are extraordinarily rare. 但这些非常罕见。 As a programmer, sometimes it is absolutely essential to have a circular class dependency in languages without this ability. 作为程序员,有时在没有这种能力的语言中拥有循环类依赖是绝对必要的。

This is where the idea of class composition comes in. Rather than inheriting a superclass, you can give a working copy of B to class A in the form of a variable. 这就是类组合的概念所在。除了继承超类之外,您还可以以变量的形式将B的工作副本提供给A类。

Another great option in some cases is to provide a conversion function, allowing B to become class A ; 在某些情况下,另一个很好的选择是提供转换功能,允许B成为A类; if they both inherit from eachother, it's very likely that they contain the same data despite their different behaviours! 如果它们都是从彼此继承的话,尽管它们的行为不同,它们很可能包含相同的数据! Some languages have the built-in ability to do this conversion. 某些语言具有执行此转换的内置功能。 The simplest example is a 'typecast'. 最简单的例子是'类型转换'。 Some languages also generalize this conversion into parametric polymorphism, where you can write a function that will work on any compatible types without needing to convert them first. 有些语言也将这种转换概括为参数多态,在这种情况下,您可以编写一个可以在任何兼容类型上运行的函数,而无需先进行转换。


Introducing a deviously hard to parse code is always a great way to catch bugs in compilers and interpreters. 引入一个难以解析的代码总是一种很好的方法来捕获编译器和解释器中的错误。 So keep this snippet in mind for when you have to write and test one! 因此,当您必须编写并测试一个时,请记住这个片段!

In some languages stuff like this is, rather than a bug, considered to be Undefined Behaviour. 在某些语言中,这样的东西,而不是一个bug,被认为是未定义的行为。 You don't want to mess with Undefined Behaviour in any code you will rely on. 您不希望在您依赖的任何代码中弄乱未定义的行为。

Nothing, the compiler rejects this code: 没什么,编译器拒绝这段代码:

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 {
                   ^

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在scala Intellij工作表中彼此依赖的两个val的初始化? - initialization of two vals depending on each other in scala Intellij worksheet? 以编程方式实现方法存根时,IntelliJ为什么默认情况下会覆盖每个方法? - Why does IntelliJ override each method by default when programatically implementing method stubs? 为什么我启动 spark stream 时 kafka 消费者代码会冻结? - Why does the kafka consumer code freeze when I start spark stream? 为什么Scala在已经具有特征的情况下会有课程? - Why does Scala have classes when it already has traits? 为什么这些代码行会冻结Scala / SBT构建? - Why does these lines of code freeze the Scala/SBT build? 为什么在打印希腊字符时IntelliJ的scala控制台会显示问号? - Why does IntelliJ's scala console display question marks when I print greek characters? 为什么IntelliJ IDEA会抛出编译错误? - Why does IntelliJ IDEA throw compilation error? Intellij为什么将文件所有权更改为root? - why does Intellij change the ownership of files to root? 使用scala插件在Intellij / maven中配置1.7时的Java 6类 - Java 6 classes when 1.7 is configured in Intellij/maven with scala plugin 单击“运行IntelliJ”时,Scala无法编译 - Scala does not Compile when clicking Run IntelliJ
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM