"Nouveau" mot-clé dans Scala

93

J'ai une question très simple: quand devons-nous appliquer le nouveau mot-clé lors de la création d'objets dans Scala? Est-ce lorsque nous essayons d'instancier uniquement des objets Java?

Bober02
la source

Réponses:

144

Utilisez le newmot - clé lorsque vous souhaitez faire référence au classpropre constructeur d'un:

class Foo { }

val f = new Foo

Omettez newsi vous faites référence à la applyméthode 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
}

Alors tu peux faire

f = Foo()

Enfin, gardez à l'esprit qu'aucune règle ne dit que la apply méthode compagnon 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: oui - Les classes Java ont rarement des objets compagnons avec une applyméthode, vous devez donc utiliser newet le constructeur de la classe réelle.

Owen
la source
1
Une classe Java ne peut jamais avoir d'objet compagnon. Il peut avoir un objet qui peut fonctionner comme Factory pour la classe Java - mais cet objet n'est pas son objet compagnon.
kiritsuku
@Antoras Puisque les classes Scala se compilent en bytecode Java et peuvent être distribuées sous forme compilée, Scala peut-il faire la différence entre un compagnon Scala réel et une classe nommée Foo $ avec un membre MODULE $ statique?
Owen
1
Je pense que scalac peut différer cela car il est spécifié qu'un objet compagnon doit être déclaré dans le même fichier que sa classe compagnon. Parce que la "propriété" du compagnon n'existe que dans Scala et non sur Bytecode, scalac doit vérifier le code Scala et non le Bytecode pour être sûr que la spécification est respectée.
kiritsuku
1
Des exemples de classes Java qui n'utilisent PAS de nouveau mot-clé dans Scala?
Bober02
De plus, les méthodes sur l'objet compagnon seront également rendues accessibles via des méthodes statiques sur la classe et cela ne se produira jamais avec les classes Java pour lesquelles vous définissez un «compagnon» plus tard.
drexin
16

Est-ce lorsque nous essayons d'instancier uniquement des objets Java?

Pas du tout. Il y a deux cas généraux lorsque vous ommit newdans 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 une classe de cas (en fait, en dessous, il y a classe + objet = modèle compagnon , par exemple ayant 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 des classes simples, 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 une classe anonyme dans scala, qui peut être construite 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
Om Nom Nom
la source
1
Ça va, mon pote?
Jacob B
0

Est-ce lorsque nous essayons d'instancier uniquement des objets Java?

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 Creator permettent d'utiliser une simple syntaxe d'appel de fonction pour créer des instances d'une classe, même si aucune méthode apply 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 de création généralisent une fonctionnalité fournie jusqu'à présent uniquement pour les classes de cas, mais le mécanisme permettant d'y parvenir est légèrement différent.
Au lieu d'une méthode apply auto-générée, nous ajoutons une nouvelle interprétation possible à un appel de fonction f(args).

VonC
la source