给定以下代码:
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 行:我的意图是将值类型“String”以及它所产生的所有属性的名称“foo”传递给产生“Attributes”的工厂“Attr”。
第 2 行:使用先前配置的属性工厂,我实际上正在生成一个名为“foo”的属性,其值为“bar”,类型为“String”。
我的结论:因为这个工厂对象的参数化类型“A”是“String”,所以 Scala 编译器推断方法“apply”的相同参数签名是“(value:String)”,这是模棱两可的。因此,我尝试通过添加隐式参数列表来改变签名。
在阅读了一篇关于类型擦除和 DummyImplicit的文章并查阅了 Scala 参考部分“7.2 隐式参数”后,我认为“(隐式假人:DummyImplicit)”可以解决问题。
目前我的解决方案是使用最小的包装器:
final case class Txt(str: String) {
override def toString = str
}
假设可以找到“Str To Txt”类型的隐式值,即合适的转换函数,则上面的第二行编译,即:
2| val catch22 = FooAttr("bar")
看来我想得太复杂了。apply
而不是用参数列表重载方法(value: String)
,我只是摆脱了它。完全符合我期望的版本现在看起来像:
final case class Attr[A](name: String)(implicit conv: String To A) {
def apply(value: A) = Attribute(name, value)
}