Pregunta Usando nuevo con Scala clase de caso final


En el Capítulo 22 del libro "Programación en Scala", el :: clase (contras) se define como

final case class ::[T](hd: T, tl: List[T]) extends List[T] {
  //...
}

los :: método en clase List se define de la siguiente manera:

def ::[U >: T](x: U): List[U] = new scala.::(x, this)

Porque es el new requerido para crear una instancia de finalcaseclass ::? ¿Es esto puramente para la desambiguación?


5
2017-12-15 02:17


origen


Respuestas:


Con las clases de casos, obtienes automáticamente un objeto complementario cuyo apply método llama al constructor, de la misma manera que puede hacer esto con una clase ordinaria:

class Foo(val value: Int) 
object Foo { def apply(value: Int) = new Foo(value) }

val x = new Foo(42)  //
val y = Foo(42)      // both work the same

Puedes instanciar clases de casos con new si quieres. En teoría, podría ser un poco más rápido porque no tiene que pasar por el objeto complementario apply Método, pero probé un punto de referencia rápido y no vi absolutamente ninguna diferencia en el rendimiento, así que supongo que está optimizado por el compilador, o simplemente una diferencia enormemente pequeña en comparación con la construcción real.

Entonces no creo que el new En el ejemplo que das, tiene algún significado y podría haber sido omitido.


6
2017-12-15 03:03



Estás en lo correcto; el new no es obligatorio Podrían haber definido el método de instancia List#:: así de igual:

def ::[U >: T](x: U): List[U] = scala.::(x, this)

(Tenga en cuenta que tenemos:

type :: = collection.immutable.::
val  :: = collection.immutable.::

definido en el scala objeto de paquete; el primero es por qué tu new scala.::(x, this) funciona, y el segundo es por qué mi scala.::(x, this) trabajos.)

La forma que usa la biblioteca llama al constructor directamente, como lo hace el tuyo. La alternativa llama al apply método del objeto compañero sintético generado para el :: clase de caso, que simplemente llama al constructor de todos modos. ¿Tal vez llamar al constructor se consideró más claro o más eficiente? (Sin embargo, las ganancias de eficiencia deberían ser casi nulas, ya que si el compilador no alinea la llamada a apply, la JVM lo hará.) Supongo que la forma más compacta:

def ::[U >: T](x: U) = ::(x, this)

podría confundirse con algún tipo de invocación recursiva extravagante (es decir, imposible), y al menos desdibuja la distinción entre la clase llamada :: y el List método llamado ::, que el Profesor Odersky se esfuerza por mantener separados para maximizar la comprensión del lector.

Espero que esto ayude.


3
2017-12-15 03:12