Parola chiave “nuova” in Scala


93

Ho una domanda molto semplice: quando dovremmo applicare la nuova parola chiave durante la creazione di oggetti in Scala? È quando proviamo a istanziare solo oggetti Java?

Risposte:


144

Usa la newparola chiave quando vuoi fare riferimento al classproprio costruttore:

class Foo { }

val f = new Foo

Ometti newse ti riferisci al applymetodo dell'oggetto associato :

class Foo { }
object Foo {
    def apply() = new Foo
}

// Both of these are legal
val f = Foo()
val f2 = new Foo

Se hai creato una classe di casi:

case class Foo()

Scala crea segretamente un oggetto compagno per te, trasformandolo in questo:

class Foo { }
object Foo {
    def apply() = new Foo
}

Quindi puoi farlo

f = Foo()

Infine, tieni presente che non esiste una regola che dice che il apply metodo companion deve essere un proxy per il costruttore:

class Foo { }
object Foo {
    def apply() = 7
}

// These do different things
> println(new Foo)
test@5c79cc94
> println(Foo())
7

E, dal momento che hai menzionato le classi Java: sì - le classi Java raramente hanno oggetti associati con un applymetodo, quindi devi usare newe il costruttore della classe effettiva.


1
Una classe Java non può mai avere un oggetto associato. Può avere un oggetto che può funzionare come Factory per la classe Java, ma questo oggetto non è il suo oggetto associato.
kiritsuku

@Antoras Poiché le classi Scala vengono compilate in bytecode Java e possono essere distribuite in forma compilata, Scala può distinguere tra un compagno Scala effettivo e una classe chiamata Foo $ con un membro MODULE $ statico?
Owen

1
Penso che scalac possa differire da questo perché è specificato che un oggetto companion deve essere dichiarato nello stesso file della sua classe companion. Poiché la "proprietà" complementare esiste solo in Scala e non su scalac a livello di Bytecode deve controllare il codice Scala e non il Bytecode per essere sicuri che la specifica venga seguita.
kiritsuku

1
Eventuali esempi di classi Java che NON utilizzano la nuova parola chiave in Scala?
Bober02

Anche i metodi sull'oggetto companion saranno resi accessibili tramite metodi statici anche sulla classe e ciò non accadrà mai con le classi java per le quali successivamente definisci un "companion".
drexin

16

È quando proviamo a istanziare solo oggetti java?

Affatto. Ci sono due casi generali in cui si omette newin scala. Con oggetti singleton (che sono spesso usati per memorizzare funzioni statiche e come una sorta di factory simile a ciò che potresti vedere in 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

Con un case class (in realtà, sotto ci sono class + object = companion pattern, ad es. Con classe e oggetto con lo stesso nome):

scala> case class Foo(bar: String) 
defined class Foo


scala> Foo("baz")
res2: Foo = Foo(baz)

Quindi, quando lavori con classi semplici, le regole sono le stesse di 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, c'è una classe anonima in scala, che può essere costruita in questo modo:

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

1
Stai bene amico?
Jacob B,

0

È quando proviamo a istanziare solo oggetti Java?

Con Scala 3 (che dovrebbe uscire a metà 2020, otto anni dopo), basato su Dotty : mai.

Scala 3 cadrà " new", come in questo thread

Le applicazioni di creazione consentono di utilizzare la sintassi delle chiamate di funzione semplice per creare istanze di una classe, anche se non è implementato alcun metodo apply.

Esempio:

class StringBuilder(s: String) {
   def this() = this(s)
}

StringBuilder("abc")  // same as new StringBuilder("abc")
StringBuilder()       // same as new StringBuilder()

Le applicazioni del creatore generalizzano una funzionalità fornita finora solo per le classi case, ma il meccanismo con cui ciò viene ottenuto è leggermente diverso.
Invece di un metodo apply generato automaticamente, aggiungiamo una nuova possibile interpretazione a una chiamata di funzione f(args).

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.