非常に簡単な質問があります。Scalaでオブジェクトを作成するときに、いつ新しいキーワードを適用すればよいですか?Javaオブジェクトのみをインスタンス化しようとしたときですか?
回答:
独自のコンストラクタnew
を参照する場合は、キーワードを使用しますclass
。
class Foo { }
val f = new Foo
new
コンパニオンオブジェクトのapply
メソッドを参照している場合は省略します。
class Foo { }
object Foo {
def apply() = new Foo
}
// Both of these are legal
val f = Foo()
val f2 = new Foo
ケースクラスを作成した場合:
case class Foo()
Scalaは密かにあなたのためにコンパニオンオブジェクトを作成し、これを次のように変えます。
class Foo { }
object Foo {
def apply() = new Foo
}
だからできる
f = Foo()
最後に、コンパニオンapply
メソッドはコンストラクタのプロキシでなければならないというルールはないことに注意してください。
class Foo { }
object Foo {
def apply() = 7
}
// These do different things
> println(new Foo)
test@5c79cc94
> println(Foo())
7
そして、Javaクラスについて言及したので、はい。Javaクラスにはapply
メソッドを持つコンパニオンオブジェクトがほとんどないためnew
、実際のクラスのコンストラクターを使用する必要があります。
Javaオブジェクトのみをインスタンス化しようとしたときですか?
どういたしまして。new
scalaで省略した場合、2つの一般的なケースがあります。シングルトンオブジェクト(静的関数を格納するためによく使用され、Javaで見られるものと同様の一種のファクトリーとして):
scala> object LonelyGuy { def mood = "sad" }
defined module LonelyGuy
scala> LonelyGuy
res0: LonelyGuy.type = LonelyGuy$@3449a8
scala> LonelyGuy.mood
res4: java.lang.String = sad
ケースクラスの場合(実際には、クラス+オブジェクト= コンパニオンパターンがあります。たとえば、クラスとオブジェクトが同じ名前である場合):
scala> case class Foo(bar: String)
defined class Foo
scala> Foo("baz")
res2: Foo = Foo(baz)
したがって、単純なクラスで作業する場合、ルールはJavaの場合と同じです。
scala> class Foo(val bar: String)
defined class Foo
scala> new Foo("baz")
res0: Foo = Foo@2ad6a0
// will be a error
scala> Foo("baz")
<console>:8: error: not found: value Foo
Foo("baz")
おまけに、次のように構築できる匿名クラスがscalaにあります。
scala> new { val bar = "baz" }
res2: java.lang.Object{val bar: java.lang.String} = $anon$1@10ee5b8
scala> res2.bar
res3: java.lang.String = baz
Javaオブジェクトのみをインスタンス化しようとしたときですか?
Dottyベースの Scala 3(2020年半ば、8年後のリリース予定):決して。
このスレッドのnew
ように、Scala 3は " " をドロップします
Creatorアプリケーションでは、applyメソッドが実装されていなくても、単純な関数呼び出し構文を使用してクラスのインスタンスを作成できます。
例:
class StringBuilder(s: String) {
def this() = this(s)
}
StringBuilder("abc") // same as new StringBuilder("abc")
StringBuilder() // same as new StringBuilder()
クリエーターアプリケーションは、これまでケースクラスにのみ提供されていた機能を一般化していますが、これを実現するメカニズムは少し異なります。
自動生成された適用メソッドの代わりに、新しい可能な解釈を関数呼び出しに追加しますf(args)
。