【问题标题】:Can not instantiate trait with no methods without empty code block无法在没有空代码块的情况下实例化没有方法的特征
【发布时间】:2020-02-28 19:56:21
【问题描述】:

我发现了一个有趣的特征:

scala> trait Thing[A]
defined trait Thing

scala> val myThing: Thing[Int] = new Thing[Int]
       error: trait Thing is abstract; cannot be instantiated

scala> val myThing: Thing[Int] = new Thing[Int] { }
myThing: Thing[Int] = $anon$1@135f160e

为什么拥有代码块允许我创建 Thing 特征的实例?

【问题讨论】:

    标签: scala traits anonymous-class


    【解决方案1】:

    这是语言的一个特性,称为匿名类。当您编写new Thing[Int] { } 时,编译器会创建一个名为$anon$1(或类似名称)的新类,该类扩展Thing[Int],然后创建$anon$1 的新实例。

    【讨论】:

      【解决方案2】:

      您不能直接实例化特征。添加{} 时,您正在创建一个可以实例化的匿名类。

      在其他地方发布了类似的问题:

      【讨论】:

        【解决方案3】:

        另一种看待它的方式是关键字new 调用了一个构造函数,但是 trait 没有构造函数,所以

        new Thing[Int]
        

        无法实例化。但是构造函数在哪里

        new Thing[Int] { }
        

        你可能会问?好吧,“空代码块”实际上定义了构造函数。这个构造函数确实没有语句(除了调用超级构造函数),但是现在new 至少有一些东西可以调用。同样,

        class Bar
        trait Qux
        
        new Bar // ok because class has a constructor (by default)
        new Qux // error because trait has no constructor
        

        在 SLS 中搜索的准确术语是 general instance creation expression,如 here 所述。

        【讨论】:

        • 我不认为在这种特殊情况下这是一种有用的方法; 1. 它没有解释new Bar {} 如何/为什么工作; 2.“块”可以包含声明,而不仅仅是语句。不过,添加到 SLS 的链接 很有用。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-04-21
        • 2021-01-07
        • 1970-01-01
        • 2015-03-18
        • 1970-01-01
        • 2015-06-18
        • 2023-03-26
        相关资源
        最近更新 更多