Antworten:
Verwenden Sie das new
Schlüsselwort, wenn Sie auf einen class
eigenen Konstruktor verweisen möchten :
class Foo { }
val f = new Foo
Lassen new
Sie weg, wenn Sie sich auf die apply
Methode des Begleitobjekts beziehen :
class Foo { }
object Foo {
def apply() = new Foo
}
// Both of these are legal
val f = Foo()
val f2 = new Foo
Wenn Sie eine Fallklasse erstellt haben:
case class Foo()
Scala erstellt heimlich ein Begleitobjekt für Sie und verwandelt es in Folgendes:
class Foo { }
object Foo {
def apply() = new Foo
}
So können Sie tun
f = Foo()
Beachten Sie zum Schluss, dass es keine Regel gibt, die besagt, dass die Companion- apply
Methode ein Proxy für den Konstruktor sein muss:
class Foo { }
object Foo {
def apply() = 7
}
// These do different things
> println(new Foo)
test@5c79cc94
> println(Foo())
7
Und da Sie Java-Klassen erwähnt haben: Ja - Java-Klassen haben selten Begleitobjekte mit einer apply
Methode, daher müssen Sie new
den Konstruktor der eigentlichen Klasse verwenden.
Ist es, wenn wir versuchen, nur Java-Objekte zu instanziieren?
Überhaupt nicht. Es gibt zwei allgemeine Fälle, in denen Sie new
in Scala verzichten. Mit Singleton-Objekten (die häufig zum Speichern statischer Funktionen und als eine Art Factory verwendet werden, die der in Java gezeigten ähnelt):
scala> object LonelyGuy { def mood = "sad" }
defined module LonelyGuy
scala> LonelyGuy
res0: LonelyGuy.type = LonelyGuy$@3449a8
scala> LonelyGuy.mood
res4: java.lang.String = sad
Bei einer Fallklasse (tatsächlich gibt es darunter Klasse + Objekt = Begleitmuster , z. B. Klasse und Objekt mit demselben Namen):
scala> case class Foo(bar: String)
defined class Foo
scala> Foo("baz")
res2: Foo = Foo(baz)
Wenn Sie also mit einfachen Klassen arbeiten, sind die Regeln dieselben wie bei 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")
Bonus, es gibt eine anonyme Klasse in Scala, die so aufgebaut werden kann:
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
Versuchen wir nur Java-Objekte zu instanziieren?
Mit Scala 3 (das Mitte 2020, acht Jahre später, veröffentlicht werden soll), basierend auf Dotty : Nie.
Scala 3 wird " new
" fallen lassen, wie in diesem Thread
Mit Creator-Anwendungen können Sie mithilfe der einfachen Funktionsaufrufsyntax Instanzen einer Klasse erstellen, auch wenn keine Apply-Methode implementiert ist.
Beispiel:
class StringBuilder(s: String) {
def this() = this(s)
}
StringBuilder("abc") // same as new StringBuilder("abc")
StringBuilder() // same as new StringBuilder()
Creator-Anwendungen verallgemeinern eine Funktionalität, die bisher nur für Fallklassen bereitgestellt wurde, aber der Mechanismus, wie dies erreicht wird, unterscheidet sich geringfügig.
Anstelle einer automatisch generierten Apply-Methode fügen wir einem Funktionsaufruf eine neue mögliche Interpretation hinzuf(args)
.