J'ai une question très simple - quand devrions-nous appliquer le nouveau mot-clé lors de la création d'objets dans Scala? Est-ce lorsque nous essayons d'instancier Java objets uniquement?
Utilisez le mot clé new
pour faire référence au propre constructeur d'un class
:
class Foo { }
val f = new Foo
Omettez new
si vous faites référence à la méthode apply
de l'objet compagnon:
class Foo { }
object Foo {
def apply() = new Foo
}
// Both of these are legal
val f = Foo()
val f2 = new Foo
Si vous avez créé une classe de cas:
case class Foo()
Scala crée secrètement un objet compagnon pour vous, le transformant en ceci:
class Foo { }
object Foo {
def apply() = new Foo
}
Vous pouvez donc faire
f = Foo()
Enfin, gardez à l'esprit qu'aucune règle ne dit que la méthode compagnon apply
doit être un proxy pour le constructeur:
class Foo { }
object Foo {
def apply() = 7
}
// These do different things
> println(new Foo)
test@5c79cc94
> println(Foo())
7
Et, puisque vous avez mentionné les classes Java: yes - Java ont rarement des objets compagnons avec une méthode apply
, vous devez donc utiliser new
et le constructeur de la classe actuelle.
Est-ce lorsque nous essayons d'instancier Java objets uniquement?
Pas du tout. Il existe deux cas généraux lorsque vous omettez new
dans scala. Avec des objets singleton (qui sont souvent utilisés pour stocker des fonctions statiques et comme une sorte d'usine similaire à ce que vous pouvez voir en 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
Avec un classes de cas (en fait, en dessous, il y a un modèle classe + objet = compagnon , par exemple avoir une classe et un objet avec le même nom):
scala> case class Foo(bar: String)
defined class Foo
scala> Foo("baz")
res2: Foo = Foo(baz)
Ainsi, lorsque vous travaillez avec une classe simple, les règles sont les mêmes qu'avec 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, il y a des classes anonymes dans scala, qui peuvent être construites comme ceci:
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
Est-ce lorsque nous essayons d'instancier Java objets uniquement?
Avec Scala 3 (qui devrait sortir mi 2020, huit ans plus tard), basé sur Dotty : jamais.
Scala 3 supprimera "new
", comme dans ce fil
Les applications créatrices permettent d'utiliser une syntaxe d'appel de fonction simple pour créer des instances d'une classe, même si aucune méthode d'application n'est implémentée.
Exemple:
class StringBuilder(s: String) {
def this() = this(s)
}
StringBuilder("abc") // same as new StringBuilder("abc")
StringBuilder() // same as new StringBuilder()
Les applications des créateurs ne généralisent une fonctionnalité fournie jusqu'à présent que pour les classes de cas, mais le mécanisme pour y parvenir est légèrement différent.
Au lieu d'une méthode d'application générée automatiquement, nous ajoutons une nouvelle interprétation possible à un appel de fonctionf(args)
.