2011-10-16 3 views
2

내가 가지고있는 유형 매개 변수 및 유형 구성원을 포함하는 중첩 된 구조 다음는 유형 매개 변수 및 유형의 회원들로부터 유형의 정보를 수집

trait B 

trait B1 extends B 

trait U { 
    type _B <: B 
} 

type U1 = U { 
    type _B = B1 
} 

class Q[_U <: U] { 
    override def toString() : String = { 
    // print out type information on B here... 
    } 
} 

def test() { 
    val q = new Q[U1]() 
    println(q.toString()) 
} 

그것은 방식 때문에 U1의 런타임에 B에 대한 형식 정보를 수집 나에게없는 것 이 지정됩니다.

내가 틀렸어? 그렇지 않은 경우, 설정에 사소한 변경 사항이있는 솔루션이 있습니까? Kipton 바로스의 대답

덕분에 내가 다음 설치를 내놓았다 :이 방법의 유일한 단점은 U.

의 인스턴스에 대한 필요성이

trait B 

trait B1 extends B 
trait B2 extends B 

trait U { 
    type _B <: B 
    implicit val mfB : Manifest[_B] 
} 

class U1 extends U { 
    type _B = B1 
    val mfB : Manifest[_B] = implicitly 
} 

class U2 extends U { 
    type _B = B2 
    val mfB : Manifest[_B] = implicitly 
} 

class Q[_U <: U](u : _U) { 
    override def toString() : String = { 
    "B: " + u.mfB.erasure.getName() 
    } 
} 

def test() { 
    println(new Q(new U1) toString) 
    println(new Q(new U2) toString) 
} 

답변

0

내가 사용하는 생각이나 했 겠어요 유형 구체화매니페스트의 조합. 전자는 추상 형식 _B을 형식 매개 변수 B으로 나타낼 수 있으며 후자는 B (편집 : 호출 컨텍스트의 정적 형식) 유형을 런타임 개체로 구체화하도록 Scala 컴파일러에 지시합니다. 내 시도는 다음과 같습니다.

trait B 
trait B1 extends B 
trait B2 extends B 
trait U { type _B <: B } 
class U1 extends U { type _B = B1 } 

class Q[B: Manifest, _U <: U { type _B = B}](u: U) { 
    override def toString() : String = { 
    implicitly[Manifest[B]].toString // Manifest[B] was an implicit parameter to Q 
    } 
} 

// Four tests: 
println(new Q[B1, U1](new U1) toString)  // (1) prints "$line1.$read$$iw$$iw$B1" 
// println(new Q[B2, U1](new U1) toString)  // (2) correctly fails to compile 
// println(new Q[Nothing, U1](new U1) toString)// (3) correctly fails to compile 
println(new Q(new U1) toString)    // (4) prints "Nothing" (why not B1?) 

명시 적 유형 매개 변수가있는 첫 번째 경우에서 작동합니다. 두 번째 경우는 U1B2 형식이 아닌 B1 형식이 포함되어 있기 때문에 제대로 컴파일되지 않습니다. 세 번째 경우에도 마찬가지입니다. 그러나 컴파일러가 B1 유형을 유추하는 것으로 보일지라도 Scala 컴파일러는 어떤 이유로 4 번째 경우에 잘못된 목록을 생성합니다. 이것이 버그인지는 충분히 알지 못하지만, 분명히 놀라운 일입니다. 누구나 case (4)가 B1의 Manifest를 인쇄하지 않는 이유를 설명 할 수 있습니까?

2

오해를 해결하기 위해 : Manifest은 유형 매개 변수의 런타임 유형을 포함하지 않습니다. 매니페스트가 필요한 메서드 또는 생성자가 호출되는 호출 사이트의 컨텍스트에서 정적 유형을 전달합니다.

scala> def foo[A: Manifest](a: A) = (manifest[A].erasure, a.asInstanceOf[AnyRef].getClass) 
foo: [A](a: A)(implicit evidence$1: Manifest[A])(java.lang.Class[_], java.lang.Class[_]) 

scala> foo("") 
res1: (java.lang.Class[_], java.lang.Class[_]) = (class java.lang.String,class java.lang.String) 

scala> foo[AnyRef]("") 
res2: (java.lang.Class[_], java.lang.Class[_]) = (class java.lang.Object,class java.lang.String) 

scala> val a: Any = "" 
a: Any = "" 

scala> foo(a) 
res3: (java.lang.Class[_], java.lang.Class[_]) = (class java.lang.Object,class java.lang.String) 
+0

감사합니다. 귀하의 요점을 명확히하기 위해 답변을 업데이트했습니다. 내 예제에서 case (4)가 Nothing을 인쇄하는 이유에 대해 생각해 보셨습니까? 호출 사이트의 타입 유추가 타입 파라미터'B'를'B1'로 결정했기 때문에 놀랍습니다. 맞습니까? –

관련 문제