我有密钥和正文案例类。假设密钥扩展了Key
特征,并且正文扩展了Body
特征。对于每个键,只有一个给定的体型。下面,我试图以编译器可以为我检查它的方式编程,它甚至似乎工作!
trait Key [T <: Body]
trait Body
case class Body1 () extends Body
case class Body2 () extends Body
case class Key1 () extends Key[Body1]
case class Key2 () extends Key[Body2]
object Tester {
def func[T <: Body](key: Key[T], body: T) = {
println("Key: "+ key, "Body: "+body)
}
val k1 = Key1()
val b1 = Body1()
val b2 = Body2()
func(k1, b1) // good match
func(k1, b2) // wrong match
}
如我所愿,上面的最后一行给出了编译时错误(见下文)。但是我可以让它更具可读性,以便我的图书馆用户能够理解正在发生的事情吗?特别是,最后的“提示”在我的案例中具有误导性。
Error:(18, 9) type mismatch;
found : A$A60.this.Key1
required: A$A60.this.Key[Product with Serializable with A$A60.this.Body]
Note: A$A60.this.Body1 <: Product with Serializable with A$A60.this.Body (and A$A60.this.Key1 <: A$A60.this.Key[A$A60.this.Body1]), but trait Key is invariant in type T.
You may wish to define T as +T instead. (SLS 4.5)
func(k1, b2)
^
答案 0 :(得分:1)
使用implicitNotFound
可以更改编译信息
import scala.annotation.implicitNotFound
trait Key[T <: Body]
trait Body
case class Body1() extends Body
case class Body2() extends Body
case class Key1() extends Key[Body1]
case class Key2() extends Key[Body2]
@implicitNotFound("Expected ${From}, but found ${To}.")
class CompileMsg[From, To]
object CompileMsg {
implicit def implValue[T] = new CompileMsg[T, T]
}
object Tester {
def func[KeyBody <: Body, BodyBody <: Body]
(key: Key[KeyBody], body: BodyBody)
(implicit msg: CompileMsg[KeyBody, BodyBody]) = {
println("Key: " + key, "Body: " + body)
}
val k1: Key1 = Key1()
val b1 = Body1()
val b2: Body2 = Body2()
func(k1, b1) // good match
func(k1, b2) // wrong match
}
现在,为您提供以下错误消息:
Error:(35, 8) keyBody is A$A57.this.Body1 != A$A57.this.Body2
func(k1, b2) // wrong match
^