[SCALA] 수비력 foo는 [A, B] (XS : (A, B) *) : 어떻게 데프 foo는 사이에 [A] (A * XS)를 구별 할 수 있습니까?
SCALA수비력 foo는 [A, B] (XS : (A, B) *) : 어떻게 데프 foo는 사이에 [A] (A * XS)를 구별 할 수 있습니까?
그 형의 삭제 그들을 그래서, 런타임에 유형이 많다는 동일 보이게 알고있다 :
class Bar {
def foo[A](xs: A*) { xs.foreach(println) }
def foo[A, B](xs: (A, B)*) { xs.foreach(x => println(x._1 + " - " + x._2)) }
}
다음과 같은 컴파일러 오류가 있습니다 :
<console>:7: error: double definition:
method foo:[A,B](xs: (A, B)*)Unit and
method foo:[A](xs: A*)Unit at line 6
have same type after erasure: (xs: Seq)Unit
def foo[A,B](xs: (A, B)*) { xs.foreach(x => println(x._1 + " - " + x._2)
) }
^
그러나 쓸 수있는 간단한 방법이있다 :
bar.foo(1, 2, 3)
bar.foo(1 -> 2, 3 -> 4)
그리고 필요없이, foo는 이러한 호출 다른 오버로드 된 버전있는 것은 명시 적으로 이름을 :
bar.fooInts(1, 2, 3)
bar.fooPairs(1 -> 2, 3 -> 4)
해결법
-
==============================
1.할 수 있습니다, 매우 라운드에 대한 방법입니다. 푸는 형 클래스이며, 컴파일러는 암시 적으로 (추정) 형식 매개 변수의 A.와 호환 형 클래스의 인스턴스를, 통과
할 수 있습니다, 매우 라운드에 대한 방법입니다. 푸는 형 클래스이며, 컴파일러는 암시 적으로 (추정) 형식 매개 변수의 A.와 호환 형 클래스의 인스턴스를, 통과
trait Foo[X] { def apply(xs: Seq[X]): Unit } object Foo { implicit def FooAny[A]: Foo[A] = new Foo[A] { def apply(xs: Seq[A]) = println("apply(xs: Seq[A])") } implicit def FooTuple2[A, B]: Foo[(A, B)] = new Foo[(A, B)] { def apply(xs: Seq[(A, B)]) = println("apply(xs: Seq[(A, B)])") } def apply[A](xs: A*)(implicit f: Foo[A]) = f(xs) } Foo(1, 2, 3) // apply(xs: Seq[A]) Foo(1 -> 2, 2 -> 3) // apply(xs: Seq[(A, B)])
제 호에서 FooAny 및 FooTuple2 둘다 전달 될 수 있지만, 컴파일러의 정적 메소드 오버로딩의 규칙에 따라, FooTuple2을 픽업. FooTuple2는 FooAny이 더 구체적으로 간주됩니다. 두 후보가 서로 구체적으로 간주하는 경우, 모호한 오류가 발생합니다. 당신은 또한 scala.LowPriorityImplicits에서 이루어집니다, 슈퍼 클래스에 하나를 배치하여 다른 이상을 선호 할 수 있습니다.
최신 정보
DummyImplicit 아이디어 및 스칼라 사용자에 대한 후속 스레드를 Riffing :
trait __[+_] object __ { implicit object __ extends __[Any] } object overload { def foo(a: Seq[Boolean]) = 0 def foo[_: __](a: Seq[Int]) = 1 def foo[_: __ : __](a: Seq[String]) = 2 } import overload._ foo(Seq(true)) foo(Seq(1)) foo(Seq("s"))
이 _의 이름이 형식 매개 변수의 형식 매개 변수 특성 __, 공변를 선언합니다. 그 동반자 개체는 __ [모든], 우리는 나중에해야하는 __의 암시 적 인스턴스를 포함하고 있습니다. foo에 두 번째와 세 번째 과부하 다시 명명 더미 유형 파라미터를 포함한다. 이것은 모든으로 추정됩니다. 이 유형의 매개 변수는 예를 들어, 추가 암시 적 매개 변수로 desugared되는 하나 개 이상의 컨텍스트 경계를 가지고 :
def foo[A](a: Seq[Int])(implicit ev$1: __[A]) = 1
다중 매개 변수 목록은 바이트 코드에서 하나의 매개 변수 목록에 연결된다, 그래서 이중 정의 문제는 회피한다.
삭제, 상황에 맞는 범위 및 암시 적 검색에 대해 배울 수있는 기회로 생각하십시오보다는 패턴이 실제 코드에 적용 할로!
-
==============================
2.우리는 단지 2 과부하를 가지고있는 경우, 우리는 Landei의 답변을 간소화하고 자동으로 당신을 위해 모든 범위로 가져 scala.Predef.DummyImplicit를 사용하여 암시 적 우리 자신을 정의 할 필요를 방지 할 수 있습니다.
우리는 단지 2 과부하를 가지고있는 경우, 우리는 Landei의 답변을 간소화하고 자동으로 당신을 위해 모든 범위로 가져 scala.Predef.DummyImplicit를 사용하여 암시 적 우리 자신을 정의 할 필요를 방지 할 수 있습니다.
class Bar { def foo[A](xs: A*) { xs.foreach(println) } def foo[A, B](xs: (A, B)*)(implicit s:DummyImplicit){ xs.foreach(x => println(x._1 + " - " + x._2)) } }
-
==============================
3.당신이 제로 인수 foo는 호출의 가능성 (빈 서열, 당신이 좋아하는 경우)을 잃는 괜찮다면,이 트릭은 도움이 될 수 있습니다 :
당신이 제로 인수 foo는 호출의 가능성 (빈 서열, 당신이 좋아하는 경우)을 잃는 괜찮다면,이 트릭은 도움이 될 수 있습니다 :
def foo[A](x: A, xs: A*) { x::xs.foreach(println) } def foo[A, B](x: (A, B), xs: (A, B)*) { (x::xs.toList).foreach(x => println(x._1 + " - " + x._2)) }
컴파일러가에 따라 차이를 만들 수 있도록, 첫 번째 매개 변수의 유형이 삭제되지 않습니다 : 지금 (이 컴파일되지 않더라도) 작동하는지 나는 확인할 수 없습니다,하지만 난 주요 아이디어는 이해하기 아주 쉽게 생각 .
이미 서열이 있고 foo는에 전달하려는 경우 불행하게도 그것은 또한 매우 편리 아니다.
-
==============================
4.
class Bar { def foo[A](xs: A*) { xs.foreach{ case (a,b) => println(a + " - " + b) case a => println(a)} } }
이 수
bar.foo(1,2) bar.foo(1->3,2->4)
그러나 또한 허용
bar.foo(1->2,5)
-
==============================
5.이것은 적은 retronym의 방법보다 복잡한 것, 그리고 켄 블룸의 DummyImplicit 솔루션의 다소 덜 장황 (이하 일반적이기는하지만) 버전입니다 :
이것은 적은 retronym의 방법보다 복잡한 것, 그리고 켄 블룸의 DummyImplicit 솔루션의 다소 덜 장황 (이하 일반적이기는하지만) 버전입니다 :
class Bar { def foo[A : ClassManifest](xs: A*) = { xs.foreach(println) } def foo[A : ClassManifest, B : ClassManifest](xs: (A, B)*) = { xs.foreach(x => println(x._1 + " - " + x._2)) } def foo[A : ClassManifest, B : ClassManifest, C : ClassManifest](xs: (A, B, C)*) = { xs.foreach(x => println(x._1 + ", " + x._2 + ", " + x._3)) } }
당신이 형 같은 수의 매개 변수 두 개의 오버로드가있는 경우이 기술은 사용할 수 있습니다 :
class Bar { def foo[A <: Int](xs: A*) = { println("Ints:"); xs.foreach(println) } def foo[A <: String : ClassManifest](xs: A*) = { println("Strings:"); xs.foreach(println) } }
-
==============================
6.방법 중 하나에 관련이없는 암시 인수는 접착제 :이이 작업을 얻을 수있는 또 다른 해키 방법입니다 :
방법 중 하나에 관련이없는 암시 인수는 접착제 :이이 작업을 얻을 수있는 또 다른 해키 방법입니다 :
class Bar { def foo[A](xs: A*) { xs.foreach(println) } def foo[A, B](xs: (A, B)*)(implicit s:String) { xs.foreach(x => println(x._1 + " - " + x._2)) } } implicit val s = "" new Bar().foo(1,2,3,4) //--> 1 //--> 2 //--> 3 //--> 4 new Bar().foo((1,2),(3,4)) //--> 1 - 2 //--> 3 - 4
from https://stackoverflow.com/questions/3422336/how-can-i-differentiate-between-def-fooaxs-a-and-def-fooa-bxs-a-b by cc-by-sa and MIT license
'SCALA' 카테고리의 다른 글
[SCALA] 평등에 대한 스칼라 함수 값을 비교하는 방법 (0) | 2019.11.24 |
---|---|
[SCALA] 스칼라 '데프 foo는 = {1}'대 '데프 foo는 {1}' (0) | 2019.11.24 |
[SCALA] 스칼라 : 왜 단위로 지능을 변환 할 수 있습니까? (0) | 2019.11.23 |
[SCALA] 하나 개의 컬럼이 다른 컬럼의 구성원 인 경우 스파크 dataframe를 필터링하는 방법 (0) | 2019.11.23 |
[SCALA] 이웃와 비교하여 목록 항목을 그룹화 (0) | 2019.11.23 |