我想创建一个 Scala Id 类型类,例如,我可以声明 Foo 类型的 Id 采用 Long 值,例如
val fooId: Id[Foo] = Id(12L) // type-safe at compile time
val fooIdValue: Long = fooId.value // able to get the value back out
我尝试了各种方法,但似乎无法强制执行这些限制。如果我声明
trait WithId[I] {
type Id = I
}
case class Id[A <: WithId[_]](value: A#Id) // A#Id => Any, not what I want!
class Foo extends WithId[Long] {
type Id = Long
}
这允许
val fooId: Id[Foo] = Id("foo") // should be illegal unless a Long
如果我将 WithId 更改为使用抽象类型
trait WithId {
type Id
}
case class Id[A <: WithId](value: A#Id)
class Foo extends WithId {
type Id = Long
}
然后
val fooId: Id[Foo] = Id(12L)
无法编译,说
no type parameters for method apply: (value: A#Id)net.box.Id[A] in object Id exist so that it can be applied to arguments (Long) --- because --- argument expression's type is not compatible with formal parameter type; found : Long required: ?0A#Id
我怎样才能说并强制执行 Id[Foo] 需要 Long?
您在
WithId
上删除该类型参数是正确的。 然而,出现的第二个问题是由您实例化 Id
的方式引起的。 当您说 val x: Foo[T]
时,您指定了您想要 x
具有的类型,但您并没有真正帮助编译器确定 Foo
在构造时应使用什么类型。 所以...编译器错误,您通过对 Foo
说您想要 Id
中的 A
得到结果,但您还没有告诉 Foo
A
是什么! 要修复它,只需将您的用法更改为
val fooId = Id[Foo](12L)