Palabra clave "nueva" en Scala

93

Tengo una pregunta muy simple: ¿cuándo deberíamos aplicar la nueva palabra clave al crear objetos en Scala? ¿Es cuando intentamos crear instancias de objetos Java solamente?

Bober02
fuente

Respuestas:

144

Utilice la newpalabra clave cuando desee hacer referencia al classpropio constructor de a:

class Foo { }

val f = new Foo

Omita newsi se refiere al applymétodo del objeto complementario :

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

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

Si ha creado una clase de caso:

case class Foo()

Scala crea en secreto un objeto complementario para usted, convirtiéndolo en esto:

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

Para que puedas hacer

f = Foo()

Por último, tenga en cuenta que no hay ninguna regla que diga que el apply método complementario debe ser un proxy del constructor:

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

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

Y, como mencionaste las clases de Java: sí, las clases de Java rara vez tienen objetos complementarios con un applymétodo, por lo que debes usar newy el constructor de la clase real.

Owen
fuente
1
Una clase Java nunca puede tener un objeto complementario. Puede tener un objeto que funcione como Factory para la clase Java, pero este objeto no es su objeto complementario.
kiritsuku
@Antoras Dado que las clases de Scala se compilan en el código de bytes de Java y se pueden distribuir en forma compilada, ¿puede Scala distinguir entre un compañero de Scala real y una clase llamada Foo $ con un miembro de MODULE $ estático?
Owen
1
Creo que scalac puede diferir de esto porque se especifica que un objeto complementario debe declararse en el mismo archivo que su clase complementaria. Debido a que la "propiedad" complementaria existe solo en Scala y no en el nivel de Bytecode, scalac tiene que verificar el código de Scala y no el Bytecode para asegurarse de que se sigue la especificación.
kiritsuku
1
¿Algún ejemplo de clases de Java que NO utilicen una nueva palabra clave en Scala?
Bober02
Además, los métodos en el objeto complementario también serán accesibles a través de métodos estáticos en la clase y eso nunca sucederá con las clases java para las que defina un "compañero" más adelante.
drexin
16

¿Es cuando intentamos crear instancias de objetos Java solamente?

De ningún modo. Hay dos casos generales en los que omite newen scala. Con objetos singleton (que a menudo se usan para almacenar funciones estáticas y como una especie de fábrica similar a lo que puede ver 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

Con clases de caso (en realidad, debajo hay clase + objeto = patrón complementario , por ejemplo, tener clase y objeto con el mismo nombre):

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


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

Entonces, cuando trabaja con clases simples, las reglas son las mismas que con 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")

Además, hay clases anónimas en scala, que se pueden construir así:

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
fuente
1
¿Estás bien, amigo?
Jacob B
0

¿Es cuando intentamos crear instancias de objetos Java solamente?

Con Scala 3 (que debería lanzarse a mediados de 2020, ocho años después), basado en Dotty : nunca.

Scala 3 soltará " new", como en este hilo

Las aplicaciones Creator permiten usar una sintaxis de llamada de función simple para crear instancias de una clase, incluso si no hay un método de aplicación implementado.

Ejemplo:

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

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

Las aplicaciones de creador generalizan una funcionalidad proporcionada hasta ahora solo para clases de casos, pero el mecanismo de cómo se logra esto es ligeramente diferente.
En lugar de un método de aplicación generado automáticamente, agregamos una nueva interpretación posible a una llamada de función f(args).

VonC
fuente