7

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

更具体地说,给定 type , 和class GenericType { ... }之间有什么区别?val a = new GenericTypeobject a extends GenericType

4

3 回答 3

10

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

  • object作为单例——每个都属于一个只存在一个实例的类;
  • object被延迟初始化——它们只会在第一次被引用时被创建/初始化;
  • 同名的anobject和 a class(or ) 是同伴trait
  • object在同伴上生成静态转发器上定义的方法class
  • 成员object可以访问同伴的私有成员class
  • 在搜索隐式时,会查看相关* 类或特征的伴随对象。

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

* 什么是“相关”类或特征是一个较长的故事——如果您有兴趣,请查看 Stack Overflow 上的问题来解释它。scala如果找不到标签,请查看 wiki 中的标签。

于 2013-04-24T04:20:34.830 回答
5

对象定义(无论它是否扩展了某些东西)意味着创建单例对象。

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
于 2013-04-24T04:05:13.137 回答
2

虽然object声明与表达式具有不同的语义new,但本地object声明的所有意图和目的都与同名的 alazy 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 )
}

test1定义a为用 的新实例初始化的惰性 val Foo,而test2定义bobject扩展的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)

object因此,尽管和 a之间存在语义差异lazy val(特别是语言对 's 的特殊处理object,如 Daniel C. Sobral 所述),alazy val总是可以用对应的代替object(并不是说这是一个很好的做法),并且作为类/特征成员的lazy val/也是如此。object我能想到的主要实际区别是该对象具有更具体的静态类型:bis of type b.type(which extends Foo) 而a恰好具有 type Foo

于 2013-04-24T10:29:51.470 回答