【发布时间】:2011-08-22 20:50:32
【问题描述】:
给定以下代码:
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)”,这是不明确的。因此,我尝试通过添加隐式参数列表来改变签名。
在阅读了一篇关于 type erasure and DummyImplicit 的文章并查阅了 Scala 参考部分“7.2 隐式参数”我认为“(implicit dummy: DummyImplicit)”可以解决问题。
目前我的解决方案是使用最小的包装器:
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)
}
【问题讨论】:
-
您能否发布一个简化的、独立的代码示例来显示您收到的错误消息?我不太明白你的意图。
-
另外:在您链接的 Stack Overflow 问题的答案中,retronym 指出:请将此视为学习擦除、上下文边界和隐式搜索的机会,而不是作为应用在实际代码中!也许有更简单的方法来实现你所需要的。
-
我更新了这篇文章,让我的意图和结论更加清晰。
标签: scala type-erasure implicits