def call = s"-6ren">
gpt4 book ai didi

scala - 早期初始化程序 `new {} with SomeTrait` 失败

转载 作者:行者123 更新时间:2023-12-01 10:32:28 26 4
gpt4 key购买 nike

在使用早期初始化语法时似乎有一个微妙之处。

trait Base { def callMe = "callMe" }
trait Proxy { this: Base => def call = s"proxied: $callMe" }

val base1 = new Base { } // non-early init works
val baseFail = new { } with Base // error: trait Base is abstract; cannot be instantiated
val base2 = new { val n=1 } with Base // why does this fix the failure?
val proxy = new { } with Base with Proxy // why doesn't this fail?

为什么 baseFail 行失败,而其他 val 却没有?

错误消息也令人困惑 - 我不是要实例化 Base,只是将其混合进去。

最佳答案

当你写 new { } with Base ,技术上没有任何早期定义。根据 SLS 5.1.6,编译器查找如下模式:

EarlyDefs         ::= `{' [EarlyDef {semi EarlyDef}] `}' `with'
EarlyDef ::= {Annotation} {Modifier} PatVarDef

虽然它没有明确说明当定义序列为空时会发生什么,但它似乎只是删除它们,因为当你编译 val a = new { val x = 1 } with Base 时,在解析阶段之后你会得到这样的东西:

val a = {
final class $anon extends Base {
val x = _;
def <init>() = {
val x = 1;
super.<init>();
()
}
};
new $anon()
}

但是如果你清空大括号,你只会得到:

 val a = new Base()

这是非法的,因为 new Base .


总结:

是一个匿名类,这是允许的:

val base1 = new Base { }

简化为 new Base ,这是非法的:

val baseFail = new { } with Base

是允许的适当的早期定义(非空):

val base2 = new { val n=1 } with Base

简化为 new Base with Proxy这也是允许的:

val proxy = new { } with Base with Proxy

new { } with Base { }也可以编译,但它与 new Base { } 完全相同, 所以没有理由那样写。

关于scala - 早期初始化程序 `new {} with SomeTrait` 失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41189393/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com