次のコードがあるとします。
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」に値型「文字列」と、それが生成するすべての属性の名前「foo」を渡すことです。
行 2: 以前に構成された属性ファクトリを使用して、実際には「String」型の値「bar」を持つ「foo」という名前の属性を作成しています。
私の結論: このファクトリ オブジェクトのパラメーター化された型 "A" は "String" であるため、Scala コンパイラーはメソッド "apply" の同じパラメーター シグネチャが "(value: String)" であると推測しますが、これはあいまいです。したがって、暗黙のパラメーター リストを追加することで、署名に違いを作ろうとしました。
型消去と DummyImplicitに関する記事を読み、Scala のリファレンス セクション「7.2 Implicit parameters」を参照した後、「(implicit dummy: DummyImplicit)」でうまくいくと思いました。
今のところ、私の解決策は最小限のラッパーを持つことです:
final case class Txt(str: String) {
override def toString = str
}
「Str To Txt」型の暗黙の値、つまり適切な変換関数が見つかった場合、上記の 2 行目がコンパイルされます。つまり、次のようになります。
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)
}