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:
Usa la new
parola chiave quando vuoi fare riferimento al class
proprio costruttore:
class Foo { }
val f = new Foo
Ometti new
se ti riferisci al apply
metodo 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 apply
metodo, quindi devi usare new
e il costruttore della classe effettiva.
È quando proviamo a istanziare solo oggetti java?
Affatto. Ci sono due casi generali in cui si omette new
in 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
È 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 funzionef(args)
.