new 演算子を使用してオブジェクトを定義することと、クラスを拡張してスタンドアロン オブジェクトを定義することの違いは何ですか?
より具体的には、 type が与えられた 場合、 とclass GenericType { ... }
の違いは何ですか?val a = new GenericType
object a extends GenericType
new 演算子を使用してオブジェクトを定義することと、クラスを拡張してスタンドアロン オブジェクトを定義することの違いは何ですか?
より具体的には、 type が与えられた 場合、 とclass GenericType { ... }
の違いは何ですか?val a = new GenericType
object a extends GenericType
実際問題として、宣言はバイトコードobject
と同じメカニズムで初期化されます。new
ただし、いくつかの違いがあります。
object
シングルトンとして -- それぞれは、インスタンスが 1 つだけ存在するクラスに属します。object
遅延初期化されます-最初に参照されたときにのみ作成/初期化されます。object
と a class
(またはtrait
) はコンパニオンです。object
は、コンパニオンで静的フォワーダーを生成しますclass
。object
、コンパニオンのプライベート メンバーにアクセスできますclass
。これらは、私がすぐに思いつく違いのほんの一部です。おそらく他にもあります。
* 「関連する」クラスまたは特性とは長い話です。興味がある場合は、それについて説明している Stack Overflow の質問を調べてください。scala
タグが見つからない場合は、Wiki でタグを参照してください。
オブジェクト定義 (何かを拡張するかどうかにかかわらず) は、シングルトン オブジェクトの作成を意味します。
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
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
test2
b
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)
object
したがって、と aのセマンティックの違いにもかかわらずlazy val
(特に、object
Daniel C. Sobral によって概説されているように、言語による 's の特別な扱い)、 alazy val
は常に対応する a に置き換えることができますobject
(それは非常に良い習慣ではありません)。クラス/特性のメンバーであるlazy val
/についても同じことが言えます。object
私が考えることができる主な実際的な違いは、オブジェクトがより具体的な静的タイプをb
持っていることです。b.type
Foo
a
Foo