2010-12-01 2 views
8

이 스칼라 코드를 감안할 때 : (5) 제대로 컴파일By-name 매개 변수가 by-value 매개 변수의 대문자와 다른 오버로드의 경우 스칼라의 동작이 왜 발생합니까?

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) 
    } 
} 

통화로 ByVal을하지만, 컴파일 요소 별명 실패

ambiguous reference to overloaded definition 

이유는 무엇입니까? 오버로드와 관련하여 by-value 및 by-name 매개 변수에 대해 동일한 동작을 관찰 할 것으로 예상됩니다 ... 어떻게 수정 될 수 있습니까?

+0

을 그것은 버그가 있습니다 ... – soc

답변

13

JVM이 "by-name"매개 변수를 지원하지 않기 때문에 스칼라가 다른 방식으로이를 구현해야하기 때문입니다. => X은 실제로 Function0[X]으로 컴파일되며 Function0[Object]으로 지워집니다. 따라서 Scala는 이름 별 매개 변수의 예상 유형에서만 다른 두 가지 방법을 구별 할 수 없습니다.

서로 다른 방법의 이름을 사용하지 않으려면, (말했듯이 된 것 외에) 과부하없이
+0

감사 다니엘이 그 이유를 설명합니다. 이제는 이것이 어떻게 실현 될 수 있습니까? –

+1

@JPP 이전에 묻은 질문입니다. 한 가지 간단한 방법은 첫 번째 인수를 필수 변수로 만들고 vararg의 일부가 아닌 것입니다. 다른 방법은 암시 적 매개 변수를 포함하지만 정확한 트릭을 기억하지 않습니다. –

+0

@JPP :이 특별한 경우에 오버로딩을 사용하지 마십시오. –

6

가능한 해결 방법 :

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") 
} 
관련 문제