鉴于以下代码:
final case class Attr[A](name: String)(implicit conv: String To A) {
def apply(value: A)(implicit dummy: DummyImplicit) = Attribute(name, value)
def apply(value: String) = Attribute[A](name, value)
}
Scala编译器在看到以下值时会抱怨“对重载定义的模糊引用”:
1| val FooAttr = Attr[String]("foo")
2| val catch22 = FooAttr("bar")
第1行:我的目的是传递给工厂“Attr”,为其生成“String”值类型“String”以及名称“foo” .
第2行:使用先前配置的属性工厂我实际上生成名为“foo”的属性,其值为“bar”,类型为“String” .
我的结论:因为这个工厂对象的参数化类型“A”是“String”,所以Scala编译器推导出方法“apply”的相同参数签名是“(value:String)”,这些参数签名是不明确的 . 因此,我尝试通过添加隐式参数列表来改变签名 .
阅读了有关type erasure and DummyImplicit的文章并查阅Scala参考部分"7.2 Implicit parameters" I thought "(implicit dummy: DummyImplicit)" would do the trick 之后 .
目前我的解决方案是使用最小的包装器:
final case class Txt(str: String) {
override def toString = str
}
鉴于可以找到“Str To Txt”类型的隐含值,即合适的转换函数,上面的第二行编译,即:
2| val catch22 = FooAttr("bar")
看来我觉得太复杂了 . 而不是使用 (value: String)
的参数列表重载 apply
方法,我只是摆脱它 . 达到我完全期望的版本现在看起来像:
final case class Attr[A](name: String)(implicit conv: String To A) {
def apply(value: A) = Attribute(name, value)
}
1 回答
这个怎么样?
属性构建器
bldr
将采用任何可转换为A == String
的B
类型的值,包括字符串本身(在这种情况下使用隐式转换Predef.conforms
) .