一个scala类中的val和对象?

PeW*_*eWu 31 scala class object

是什么声明字段作为之间的差异val,lazy val以及objectScala的类中,如下面的代码片断:

class A

class B {
  val a1 = new A      { def foo = 1 }
  object a2 extends A { def foo = 1 }
  lazy val a3 = new A { def foo = 1 }
}
Run Code Online (Sandbox Code Playgroud)

Rex*_*err 21

在前者中,包含的任何代码在创建B类时立即执行.但是,在后者中,直到您实际使用该对象,它才会被实例化.

你可以在这里看到差异:

class A { println("Creating a new A") }
class B {
  val a1 = new A { println("a1"); def foo = 1 }
  object a2 extends A { println("a2"); def foo = 1 }
}

scala> val b = new B
Creating a new A
a1
b: B = B@1176e8a

scala> b.a2.foo
Creating a new A
a2
res0: Int = 1
Run Code Online (Sandbox Code Playgroud)

创建的.class文件的名称也存在隐藏的差异等等; 当然,两者有不同的类型.

  • 对于它的价值,懒惰的val似乎比我读过的Scala代码中的对象成员更受欢迎.如果你在野外看到一个对象成员,它可能来自2.6之前的Scala,当时引入了懒惰的val. (3认同)
  • 天生就是,不,不是我所知道的.`object`的字节码更紧凑.我不确定这是否意味着`lazy val`写得不好,或者`object`在某些线程条件下是否可能不安全,或者两者兼而有之. (2认同)

Aar*_*rup 19

我不确定aioobe是否认识到他的答案的重要性,但不同的类型实际上代表了vals和之间的关键区别objects.特别地,vallazy val具有结构式(例如A{def foo: Int}),而object具有单型.因此,foovals上的foo方法的调用涉及反射,而对方法的调用object则不包括:

class A

class B {
  val a1 = new A      { def foo = printStack }
  object a2 extends A { def foo = printStack }
  lazy val a3 = new A { def foo = printStack }

  def printStack() = 
     new Exception().getStackTrace take 3 foreach println
}

scala> val b = new B
b: B = B@5c750

scala> b.a1.foo   // the val
line124$object$$iw$$iw$B.printStack(<console>:12)
line124$object$$iw$$iw$B$$anon$1.foo(<console>:7)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

scala> b.a2.foo   // the object
line124$object$$iw$$iw$B.printStack(<console>:12)
line124$object$$iw$$iw$B$a2$.foo(<console>:8)
line128$object$$iw$$iw$.<init>(<console>:9)

scala> b.a3.foo   // the lazy val
line124$object$$iw$$iw$B.printStack(<console>:12)
line124$object$$iw$$iw$B$$anon$2.foo(<console>:9)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
Run Code Online (Sandbox Code Playgroud)

  • @Luigi Plinge匿名类仅对父类/接口中未定义的方法使用反射.如果`A`定义了`foo`,即使是抽象的,也不需要反思. (3认同)

Ale*_*ert 18

一个主要的区别是val可以被覆盖,而对象则不能.

class C extends B {                           
  override val a1 = new A { def foo = 2 }     
  override object a2 extends A { def foo = 2 }
}
Run Code Online (Sandbox Code Playgroud)

导致:

<console>:9: error: overriding object a2 in class B of type object C.this.a2;
object a2 cannot be used here - classes and objects cannot be overridden
override object a2 extends A { def foo = 2 }
Run Code Online (Sandbox Code Playgroud)