2013-04-24 82 views
7

使用new运算符定义对象与通过扩展类定义独立对象之间的区别是什么?斯卡拉 - 新的vs对象扩展

更具体而言,给定类型class GenericType { ... }val a = new GenericTypeobject a extends GenericType之间的区别是什么?

+0

可能重复[val和对象在scala类内?](http://stackoverflow.com/questions/3448691/val-and-object-inside-a-scala-class) – Bergi 2016-05-25 04:00:25

回答

9

作为一个实际问题,object声明初始化为相同的机制如在字节码new。但是,有很多不同之处:

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

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

*什么是“相关”类或性状是一个更长的故事 - 查找堆栈溢出问题,如果你有兴趣解释它。如果您无法找到它们,请查看scala标记的维基。

4

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

scala> class GenericType 
defined class GenericType 

scala> val a = new GenericType 
a: GenericType = [email protected] 

scala> val a = new GenericType 
a: GenericType = [email protected] 

scala> object genericObject extends GenericType 
defined module genericObject 

scala> val a = genericObject 
a: genericObject.type = [email protected] 

scala> val a = genericObject 
a: genericObject.type = [email protected] 
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) 
} 

test1限定a作为懒惰VAL与Foo新实例初始化,而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), a lazy val总是可以用相应的object代替(这不是一种非常好的做法),同样也适用于属于类/特征成员的lazy val/object。 我能想到的主要实际区别是对象具有更具体的静态类型:b类型为b.type(它扩展了Foo),而a恰好类型为Foo

+0

lazy val a:Foo =一个 – 2014-07-11 10:52:55