我在类型安全构建器模式中使用幻像类型,以确保只调用一次方法,如下面的代码示例所示
sealed trait TBoolean
sealed trait TTrue extends TBoolean
sealed trait TFalse extends TBoolean
class Builder[MethodCalled <: TBoolean] private() {
def foo()(implicit ev: MethodCalled =:= TFalse): Builder[TTrue] = {
new Builder[TTrue]
}
}
object Builder {
def apply() = new Builder[TFalse]()
}
Builder().foo().foo()
无法按要求运行,但我想将错误消息设置为用户可读的内容。目前消息是
此行有多个标记 - 方法foo没有足够的参数:(隐式ev:=:= [W.TTrue,W.TFalse])W.Builder [W.TTrue]。未指定的值参数ev。 - 无法证明W.TTrue =:= W.TFalse。 - 无法证明W.TTrue =:= W.TFalse。
答案 0 :(得分:5)
在这里使用类型参数有点过分。最好从foo
方法返回一个功能较弱的类型:
object Builder {
trait CanFoo { def foo() : Builder }
def apply(): Builder with CanFoo = new Builder with CanFoo {
def foo() = new Builder {}
}
}
trait Builder
Builder().foo().foo() // value foo is not a member of Builder
有一个注释implicitNotFound
can be used可以自定义错误消息,但需要使用所寻找的类型(=:=
)来定义,而不是使用use site({ {1}}),so that is a pretty useless construction ...
...除非您为foo
创建自己的替代品:
=:=
答案 1 :(得分:2)
您无法自定义错误消息,但可以自定义您的特征名称。我会称他们为Built
和Unbuilt
或类似的东西。然后你可以警告库的用户或任何你会得到看似毛茸茸的错误信息,但他们真的只需要发现看起来像Cannot prove that Built =:= Unbuilt
的东西。