我有一个类型类,我想用它来存储一种对象:
trait RetainType {
type A
}
object RetainType {
def apply[A0](): RetainType = new RetainType{
type A = A0
}
}
鉴于以下课程:
trait Annotation
class Entity extends Annotation
我希望编译器证明RetainType.A
扩展Annotation
:
def hasAnnotation[A <: Annotation] = Unit
但是使用RetainType
编译器似乎无法解决这个问题:
val retainType = RetainType[Entity]
hasAnnotation[RetainType.A] //throws an error: type arguments [retainType.A] do not conform to method hasAnnotation's type parameter bounds [A <: Annotation]
如果指定了类型,它就可以了:
hasAnnotation[Entity] //works fine
无论如何编译器可以证明这种关系吗?
答案 0 :(得分:5)
你搞砸了RetainType.apply
的签名:
def apply[A0](): RetainType
返回类型未提及A0
,因此它已被遗忘&#34;。也就是说,
val x = RetainType[Int]
x.A
完全是抽象的;编译器无法证明x.A = Int
,因为apply
的签名会删除该信息。使用细化类型:
object RetainType {
def apply[A0](): RetainType { type A = A0 } = new RetainType { override type A = A0 }
}
您可能希望使用Aux
模式来更好地使用:
object RetainType {
type Aux[A0] = RetainType { type A = A0 }
def apply[A0](): RetainType.Aux[A0] = new RetainType { override type A = A0 }
}