eje*_*211 2 scala traits anonymous-class
我知道有两种方法可以创建匿名类来实例化 Scala 中的特征:
scala> trait SomeTrait {
| def aUsefulMethod = ()
| }
defined trait SomeTrait
scala> val instance1 = new SomeTrait{} // Method 1
instance1: SomeTrait = $anon$1@7307556f
scala> instance1.aUsefulMethod // Returns a Unit.
scala> object instance2 extends SomeTrait // Method 2
defined module instance2
scala> instance2.aUsefulMethod // Returns a Unit.
Run Code Online (Sandbox Code Playgroud)
我想不出它们不相等的原因。我错了吗?
我问这个问题的部分原因是我以前只知道方法 2,但现在我发现方法 1 更常见。所以我想知道我是否一直做错了什么。
第一种方法new Trait {}创建一个新class实例。
第二种方法创建一个object单例。
人们可以在 REPL 中看到这一点:
scala> trait Example {}
defined trait Example
Run Code Online (Sandbox Code Playgroud)
每次调用 new 都会返回一个新的实例。可以看到每个对象都有一个新地址。
scala> new Example{}
res0: Example = $anon$1@768debd
scala> new Example{}
res1: Example = $anon$1@546a03af
Run Code Online (Sandbox Code Playgroud)
这里单例对象被创建一次。
scala> object X extends Example
defined object X
scala> X
res2: X.type = X$@1810399e
scala> X
res3: X.type = X$@1810399e
Run Code Online (Sandbox Code Playgroud)
即使这两种方法表面上看起来相似,但它们会导致不同的结果。
scala> new Example{} == new Example{}
<console>:12: warning: comparing values of types Example and Example using `==' will always yield false
new Example{} == new Example{}
^
res4: Boolean = false
scala> X == X
res5: Boolean = true
Run Code Online (Sandbox Code Playgroud)
在底层结构上,这两种方法都会导致*class在运行时生成不同的文件JVM
$ cat example.scala
object Example1 {
trait A
new A {}
}
$ scalac example.scala
$ ls *class
Example1$$anon$1.class Example1$A.class
Example1$.class Example1.class
$ cat example2.scala
object Example2 {
trait A
object X extends A
}
$ scalac example2.scala
$ ls *class
Example2$.class Example2$X$.class
Example2$A.class Example2.class
Run Code Online (Sandbox Code Playgroud)