Scala - 新vs对象扩展

时间:2013-04-24 03:13:17

标签: scala

使用new运算符定义对象与通过扩展类定义独立对象有什么区别?

更具体地说,鉴于类型class GenericType { ... }val a = new GenericTypeobject a extends GenericType之间有什么区别?

3 个答案:

答案 0 :(得分:9)

实际上,object声明在字节码中使用与new相同的机制进行初始化。但是,有很多不同之处:

  • object作为单身人士 - 每个人都属于一个只存在一个实例的类;
  • object被懒惰地初始化 - 它们只会在第一次被引用时被创建/初始化;
  • 同名的objectclass(或trait随播广告;
  • object上定义的方法会在随播广告class上生成静态转发器;
  • object的成员可以访问随播广告class;
  • 的私人成员
  • 在搜索implicits时,会查看相关*类或特征的伴随对象。

这些只是我能想到的蝙蝠的一些差异。可能还有其他人。

*什么是“相关”类或特征是一个较长的故事 - 如果您感兴趣,可以在Stack Overflow上查找解释它的问题。如果您无法找到scala标签,请查看维基。

答案 1 :(得分:4)

对象定义(无论是否扩展)都意味着单例对象的创建。

scala> class GenericType
defined class GenericType

scala> val a = new GenericType
a: GenericType = GenericType@2d581156

scala> val a = new GenericType
a: GenericType = GenericType@71e7c512

scala> object genericObject extends GenericType
defined module genericObject

scala> val a = genericObject
a: genericObject.type = genericObject$@5549fe36

scala> val a = genericObject
a: genericObject.type = genericObject$@5549fe36

答案 2 :(得分:2)

虽然object声明的语义与new表达式的语义不同,但本地object声明适用于所有意图,其目的与lazy val相同。名称。考虑:

class Foo( name: String ) {
  println(name+".new")
  def doSomething( arg: Int ) {
    println(name+".doSomething("+arg+")")
  }
}

def bar( x: => Foo ) {
  x.doSomething(1)
  x.doSomething(2)
}

def test1() {
  lazy val a = new Foo("a")
  bar( a )
}

def test2() {
  object b extends Foo("b")
  bar( b )
}

test1a定义为使用新Foo实例初始化的lazy val,而test2b定义为object扩展Foo。 从本质上讲,它们都懒惰地创建Foo的新实例,并为其命名(a / b)。

您可以在REPL中尝试并验证它们的行为相同:

scala> test1()
a.new
a.doSomething(1)
a.doSomething(2)

scala> test2()
b.new
b.doSomething(1)
b.doSomething(2)

尽管objectlazy val之间存在语义差异(特别是语言对object的特殊处理,如Daniel C. Sobral所述), lazy val总是可以用相应的object代替(不是这是一个非常好的做法),同样适用于lazy val / object的成员一个阶级/特质。 我能想到的主要实际区别是对象具有更具体的静态类型:b类型为b.type(扩展Foo)而a具有确切的类型类型Foo