你是对的,
this.type
需要使用,但有一些限制:
trait EnforceIdType {
def id: Id[_ >: this.type <: EnforceIdType]
}
case class A(id: Id[A]) extends EnforceIdType
case class B(id: Id[B]) extends EnforceIdType
//case class C(id: Id[B]) extends EnforceIdType // Won't compile, as expected
更新时间:
关于第二个限制(由Alexey Romanov展示)。它可以消除,但需要很长的路:
//Embeded polymorphism used
class Id(val value: Long) {
type M
}
// Factory method for shift type variable to type parameter field
object Id {
def apply[T](value : Long) = new Id(value) { type M = T }
}
trait EnforceIdType {
type This = this.type // store this.type for use inside Id { type M = .. }
val id: Id { type M >: This <: EnforceIdType } // need to be val
def show(x : id.M) { println (x) } // dependent method
}
case class A(id: Id { type M = A }) extends EnforceIdType
case class B(id: Id { type M = B }) extends EnforceIdType
// case class C(id: Id { type M = B }) extends EnforceIdType // Won't compile, as expected
val a = A( Id[A](10))
val b = B( Id[B](10))
a.show(a)
// a.show(b) // Won't compile, as expected