web-dev-qa-db-fra.com

"nouveau" mot clé dans Scala

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?

87
Bober02

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.

132
Owen

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
15
om-nom-nom

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 fonction f(args).

0
VonC