2011-08-10 3 views
6

De acuerdo con la especificación Scala, el extractor construido por clases de casos es la siguiente (especificación de Scala §5.3.2):Diferencia entre el hogar hizo extractora y la caja extractora clase

def unapply[tps](x: c[tps]) = 
    if (x eq null) scala.None 
    else scala.Some(x.xs11, ..., x.xs1k) 

Por razones de implementación, quiero ser capaz de imitar el comportamiento de este extractor en una clase que no sea case. Sin embargo, mi implementación no reproduce el mismo comportamiento.

Aquí es un ejemplo de la diferencia que tengo:

trait A 

sealed trait B[X <: A]{ val x: X } 

case class C[X <: A](x: X) extends B[X] 

class D[X <: A](val x: X) extends B[X] 

object D { 
    def unapply[X <: A](d: D[X]): Option[X] = 
    if (d eq None) None 
    else Some(d.x) 
} 

def ext[X <: A](b: B[X]) = b match { 
    case C(x) => Some(x) 
    case D(x) => Some(x) 
    case _ => None 
} 

tengo la siguiente advertencia:

<console>:37: warning: non variable type-argument X in type pattern D[X] is unchecked since it is eliminated by erasure 
    case D(x) => Some(x) 

Aviso de la advertencia se produce sólo en el caso D, no en el caso de la clase caja textractor. ¿Tiene alguna idea sobre la causa de la advertencia/sobre lo que debo hacer para evitar esta advertencia?

Nota: Si desea probarlo en REPL, la forma más fácil es:

  1. Para activar la advertencia sin control

    Scala>: el poder

    Scala> settings.unchecked .value = verdadero

  2. Para copiar el código anterior en modo pegar:

    Scala>: pasta

    [copiar/pegar]

    [Ctrl + D]

Editar: Como se mencionó Antoras debe ser un error del compilador, tal vez la versión Scala podría ser útil: scala 2.9.0.1 (después de una prueba rápida, sigue ahí en scala 2.9.1RC2)

Respuesta

2

Esto parece ser un error del compilador. Analicé el resultado del compilador AST (con fsc -Xprint:typer <name_of_file>.scala). Interpreta ambos como lo mismo:

... 
    final <synthetic> object C extends java.lang.Object with ScalaObject with Serializable { 
     def this(): object test.Test.C = { 
     C.super.this(); 
     () 
     }; 
     final override def toString(): java.lang.String = "C"; 
     case <synthetic> def unapply[X >: Nothing <: test.Test.A](x$0: test.Test.C[X]): Option[X] = if (x$0.==(null)) 
     scala.this.None 
     else 
     scala.Some.apply[X](x$0.x); 
     case <synthetic> def apply[X >: Nothing <: test.Test.A](x: X): test.Test.C[X] = new test.Test.C[X](x); 
     protected def readResolve(): java.lang.Object = Test.this.C 
    }; 
... 
    final object D extends java.lang.Object with ScalaObject { 
     def this(): object test.Test.D = { 
     D.super.this(); 
     () 
     }; 
     def unapply[X >: Nothing <: test.Test.A](d: test.Test.D[X]): Option[X] = if (d.eq(null)) 
     scala.None 
     else 
     scala.Some.apply[X](d.x) 
    }; 
... 

La firma del método de ambos métodos no se aplica son idénticos.

Además, el código funciona bien (como se esperaba debido a los métodos idénticos):

trait A { 
    def m = "hello" 
} 

class AA extends A 

sealed trait B[X <: A]{ val x: X } 

case class C[X <: A](x: X) extends B[X] 

class D[X <: A](val x: X) extends B[X] 

object D { 
    def apply[X <: A](x: X) = new D(x) 
    def unapply[X <: A](d: D[X]): Option[X] = 
    if (d eq null) None 
    else Some(d.x) 
} 

def ext[X <: A](b: B[X]) = b match { 
    case C(x) => Some("c:"+x.m) 
    case D(x) => Some("d:"+x.m) 
    case _ => None 
} 
println(ext(C[AA](new AA()))) 
println(ext(D[AA](new AA()))) 
+0

¿Te creo que tenemos material suficiente para abrir un billete? – Nicolas

+0

Sí, creo que es suficiente. Hay una advertencia, pero el código funciona bien. Además, el código generado también funciona bien y es idéntico. – sschaef

Cuestiones relacionadas