이 유형 감시는 또한 기능이기 때문입니다. Predef
로 선언 :
sealed abstract class <:<[-From, +To] extends (From => To) with Serializable
그래서 A <:< JsValue
도 기능 (A) => JsValue
이다. 함수가 무엇을하는지 궁금 할 수 있습니다. 아무 것도하지 않고 A
을 사용하고 직접 반환합니다 (JsValue
).
sealed trait Root { def bip() { println("bip") } }
def makeBip[A <: Root](a: A) {
a.bip() // works because a is known to the type system to be a Root
}
def makeBip2[A](a: A)(implicit ev: A <:< Root) {
a.bip() // works, because implicit resolution turns it into `ev(a).bip()`
}
도 비록 당신이 a
증거에 Root
감사 것을 알고 때문에 makeBip2
가 암시하지 않고 컴파일되지 것이다 마지막 방법, 유형이이 예제를 고려 유용한 이유
은 참조하십시오 시스템은 그렇지 않습니다. 당신은 그것을 캐스팅 할 수 있습니다, 그것은 일하게 될 것입니다 :
def makeBip3[A](a: A)(implicit ev: A <:< Root) {
a.asInstanceOf[Root].bip() // ugly
}
그러나 이것은 옳지 않습니다. 단지 당신이 a
을 Root
으로 변환하는 방법을 가지고 있다면 ... 그러나 기다리십시오, 당신은 : 증거 그 자체! 암시 적 매개 변수는 메소드 내 implicits으로 사용할 수 있기 때문에
def makeBip4[A](a: A)(implicit ev: A <:< Root) {
ev(a).bip() // works!
}
는 그리고, a.bip()
자동 ev(a).bip()
으로 변환됩니다 당신은 함수가 포함 된 알 필요가 없습니다.
그러나, 타입 시스템 만 Reads[JsValue]
으로하는 A JsValue
에 A
아니지만 Seq[A]
Seq[JsValue]
로 또는 Reads[A]
를 해결하기 위해 암시를 사용합니다.
그래서 당신이 경우에, this.map(witness)
단지 형 시스템이 Reads[A]
이가 JsValue
를 취하고 B
을 반환 뭔가로 구성 될 수 있도록, 아무것도하지 않는 해당 기능을 적용하여 Reads[JsValue]
을 것을 이해한다.
자세한 내용은 Generalized type constraits 질문을 참조하십시오.