我想创建一个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]需要很长时间?
答案 0 :(得分:3)
你在WithId
上摆脱那个类型参数是对的。但是,出现的第二个问题是由于您如何实例化Id
。当你说val x: Foo[T]
时,你指的是你希望x
拥有什么类型,但是你并没有真正帮助编译器找出Foo
应该使用的类型建造。所以...你得到Foo
Id
A
Foo
的结果导致编译错误,但你没有告诉A
什么val fooId = Id[Foo](12L)
甚至是!要解决此问题,只需将您的使用情况更改为
{{1}}