2012-01-15 2 views
1

스칼라에서 스칼라 매니페스트를 통해 주어진 클래스의 유형을 가져 와서 저장하고 있습니다. 내 질문은 어떻게 원래 클래스가 한 부모 클래스 또는 다른 클래스에서 유래했는지 확인하기 위해 해당 형식을 확인할 수 있습니까? 나 때문에 형의 삭제의 t: Class[MyParentClass]에 패턴 일치를 수행 할 수 없습니다처럼스칼라 구체화 유형이 특정 부모 클래스를 확장하는지 확인하는 방법은 무엇입니까?

그것은 다음과 같이 보인다 :

trait Product 
trait PerishableProduct extends Product 

class Fridge extends Product 
class Banana extends PerishableProduct 

def getProductType[P <: Product](implicit manifestP: Manifest[P]): Class[P] = 
    manifestP.erasure.asInstanceOf[Class[P]] 

val isPerishable = getProductType[Fridge] match { 
    case x: Class[PerishableProduct] => true 
    case _ => false 
} 
// ^^ warning: non variable type-argument PerishableProduct in type pattern 
// Class[PerishableProduct] is unchecked since it is eliminated by erasure 

내가 부족 또 다른 트릭이 있습니까?

답변

10

어떻게 좋은 오래된 반사에 대한 :

def isPerishable[P](implicit m: Manifest[P]): Boolean = 
    classOf[PerishableProduct].isAssignableFrom(m.erasure) 

isPerishable[Fridge] // false 
isPerishable[Banana] // true 
+0

와우 덕분에 Sciss - 훌륭합니다. 'classOf [GroupedPerishableProduct [_]] .isAssignableFrom (bananasType)' –

5

문제는 당신이 유형의 삭제를 처리 할 때 당신이 매니페스트 필요하다. Manifest는 < : <으로이 테스트를 수행하는 쉬운 방법을 제공합니다.

println(manifest[Fridge] <:< manifest[PerishableProduct]) 
println(manifest[Banana] <:< manifest[PerishableProduct]) 

위 항목에는 직접 유형 참조가 있으므로 getProductType을 업데이트하지만 사용됩니다.

def getProductType[P <: Product](implicit manifestP: Manifest[P]): Manifest[P] = manifestP 
val isPerishable = getProductType[Fridge] <:< manifest[PerishableProduct] 
println(isPerishable) 
+0

많은 감사 ** Neil ** - 이전에'<: <'를 만나지 않았으므로 매우 유용합니다. 불행히도 이것은 저에게 효과가 없을 것입니다 - 비교 시점에서'manifest [P] '가 아니라'manifestP.erasure.asInstanceOf [Class [P]]'만 사용할 수 있기 때문입니다. –

관련 문제