2010-12-01 26 views
8

Teniendo en cuenta este código Scala:¿Por qué el comportamiento de Scala en caso de sobrecarga con parámetros de nombre diferente del caso con parámetros de valor por defecto?

object test { 

    def byval(a: Int) = println("Int") 
    def byval(a: Long) = println("Long") 

    def byname(a: => Int) = println("=> Int") 
    def byname(a: => Long) = println("=> Long") 

    def main(args: Array[String]) { 
     byval(5) 
     byname(5) 
    } 
} 

el ByVal de llamada (5) compila correctamente, pero falla al compilar sobrenombre:

ambiguous reference to overloaded definition 

¿Por qué? Esperaría observar el mismo comportamiento para los parámetros by-value y by-name con respecto a la sobrecarga ... ¿Cómo se puede arreglar?

+0

Podría ser un error ... – soc

Respuesta

13

Esto se debe a que JVM no admite un parámetro "por nombre", por lo que Scala tiene que implementarlo de otra manera. => X en realidad compila a Function0[X], que se borra a Function0[Object], lo que hace que Scala no pueda distinguir dos métodos que difieren solo por el tipo esperado de un parámetro de nombre.

+0

Gracias Daniel, este explica el porqué Ahora, ¿cómo se puede trabajar esto (si es posible)? –

+1

@JPP Esa es una pregunta que se ha hecho antes. Una manera simple sería hacer obligatorio el primer argumento y no ser parte de la vararg. Otros métodos implican parámetros implícitos, pero no recuerdo los trucos exactos. –

+0

@JPP: No utilice la sobrecarga en este caso particular. –

6

solución posible sin sobrecargar (además de lo que se ha dicho antes), si no se desea utilizar diferentes nombres de método:

def byname[A](a: => A)(implicit manifest:Manifest[A]) = 
manifest.erasure match { 
    case erasure if(erasure.isAssignableFrom(classOf[Long])) => println("=> Long") 
    case erasure if(erasure.isAssignableFrom(classOf[Int])) => println("=> Int") 
} 
Cuestiones relacionadas