2011-09-07 11 views
12

después de enterarme de que las clases de caso extienden el Producto, me pregunté por qué no extienden ProductN. Por ejemplo, dado un código como:¿Por qué las clases de casos solo se extienden Producto y no Producto1, Producto2, ..., ProductoN?

case class Foo(a: Int) 

yo esperaría Foo(1).asInstanceOf[Product1[Int]] para trabajar, pero no lo hace (comprobado con Scala 2.9.1, y confirmado por otras fuentes y por Product documentación).

que estaba interesado en esto, porque quería declarar clases, tales como:

abstract class UnaryOp[T1 <: Exp[_], R](t1: T1) extends Exp[R] { 
    this: Product1[T1] => 
} 

De esta manera, un nodo para una operación singular deben aplicar producto1. Sería bueno si ser simplemente una clase de caso con un parámetro sería suficiente para esto.

+0

Estoy confundido acerca de la votación negativa aquí. ¿Podría explicar el infractor? – Blaisorblade

Respuesta

11

Considera:

case class X(n: Int) 
case class Y(x: String, y: Int) extends X(y) 

Si las clases de casos extendidos ProductN, a continuación, que se extendería tanto Product1 y Product2, pero el parámetro Tipo de cambios, por lo que hay dos sobrecargas diferentes para _1. Este es solo un problema: apuesto a que hay otros.

Ahora, la clase de caso que hereda clase de clase ha quedado en desuso, y Martin Odersky está considerando hacer que hereden ProductN. AFAIK, aún no se ha hecho, pero el obstáculo ha sido eliminado.

+4

Sí, con suerte esto lo convertirá en una futura versión de Scala, ya que permite escribir funciones de descomposición genéricas seguras de clases de casos. –

+1

¿Es posible heredar clases de casos en Scala? – Taky

0

Si Product1[Int] se hubiera ampliado automáticamente, también se debería proporcionar el val _1: Int. Aunque podría imaginarse, podría automatizarse que a se asigne a _1, etc., pero no lo es. Probablemente solo para no complicar aún más las cosas.

+0

Agregar 'val _1: Int' desperdiciará memoria en cada instancia, pero' Product1 [T] 'tiene una definición abstracta' def _1: T', y agrega una implementación para eso ('def _1: T = a'' doesn) No cambie el tamaño de la instancia. ¡Vea la respuesta de Daniel C. Sobral! – Blaisorblade

+0

Sí, tienes razón. Debo haberlo pasado por alto. – agilesteel

+1

¿Qué pasaría aquí? case class C (_2: String, _1: Int) – nafg

3

Lo traje de vuelta poco después de que Martin dijera que podía hacerlo. Todavía no funciona, pero en la medida que lo hace, está detrás de -Xexperimental en compilaciones de troncales.

scala> case class Foo[T, U](x1: T, x2: U) 
defined class Foo 

scala> Foo(List("a"), "b") 
res0: Foo[List[java.lang.String],java.lang.String] = Foo(List(a),b) 

scala> res0.isInstanceOf[Product2[_,_]] 
res1: Boolean = true 
+0

Gracias, eso es genial. ¡Sería bueno tener eso para el próximo lanzamiento de Scala! No estaba seguro de qué respuesta aceptar, pero en ese sentido creo que todavía tengo que aceptar la respuesta de Daniel C. Sobral para proporcionar la explicación. – Blaisorblade

+0

Probé esto en 2.10.0-M5, con resultados confusos. _1 y _2 están presentes en Foo, pero no es un subtipo de Product2, y estos miembros no están documentados por Scaladoc: '' 'scala> Foo (Lista (" a ")," b ") res10: Foo [Lista [String], String] = Foo (Lista (a), b) Scala> res10.isInstanceOf [Producto2 [_, _]] res11: Boolean = false Scala> res10._1 res12: Lista [cadena ] = Lista (a) scala> Algunos (1) ._ 1 res13: Int = 1''' – Blaisorblade

Cuestiones relacionadas