类型安全的Builder:如何设置编译器错误消息

时间:2013-01-12 11:16:44

标签: scala

我在类型安全构建器模式中使用幻像类型,以确保只调用一次方法,如下面的代码示例所示

  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。

2 个答案:

答案 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)

您无法自定义错误消息,但可以自定义您的特征名称。我会称他们为BuiltUnbuilt或类似的东西。然后你可以警告库的用户或任何你会得到看似毛茸茸的错误信息,但他们真的只需要发现看起来像Cannot prove that Built =:= Unbuilt的东西。