这一点都不奇怪。让我们看第一个例子:
您声明您的类ABC以接收一个按名称传递的参数,该参数返回Unit并且您认为这个片段:
val x = new ABC {
a + b
}
正在传递该body参数,它不是。真正发生的是:
val x = new ABC(()) { a + b }
如果您运行该代码,您将看到println(body) prints ()因为您没有为body参数传递值,编译器允许它编译,因为正如 scaladoc 所述,只有 1 个 type 值Unit:
Unit 是 scala.AnyVal 的子类型。Unit 类型的值只有一个,(),并且它不被底层运行时系统中的任何对象表示。具有返回类型 Unit 的方法类似于声明为 void 的 Java 方法。
由于只有一个值,编译器允许您省略它,它将填补空白。单例对象不会发生这种情况,因为它们不扩展AnyVal。Just has the default value for Intis0的默认值Unit,()因为只有这个值可用,所以编译器接受它。
从文档:
如果 ee 具有某个值类型并且预期类型是 Unit,则通过将 ee 嵌入到术语 { ee; 中将其转换为预期类型。() }。
单例对象不会扩展AnyVal,因此它们不会得到相同的对待。
当您使用如下语法时:
new ABC {
// Here comes code that gets executed after the constructor code.
// Code here can returns Unit by default because a constructor always
// returns the type it is constructing.
}
您只是在构造函数主体中添加内容,而不是传递参数。
第二个示例无法编译,因为编译器无法推断默认值,body: => Int因此您必须显式传递它。
结论
构造函数的括号内的代码与传递参数不同。在相同的情况下它可能看起来相同,但这是由于“魔法”。