Scala传递式隐式转换

6
我有三个Scala类(A、B、C)。
我有一个从A转换为B的隐式转换,以及一个从B转换为C的隐式转换。
在我的代码中的某个时刻,我想在A上调用C方法。这可能吗?
我提出的一个解决方案是从A到C进行转换,但这似乎有些冗余。
注意:
当我在A上调用B方法时,它可以工作。
当我在B上调用C方法时,它可以工作。
当我在A上调用C方法时,它说在A的主体中找不到该方法。
谢谢...

6
提示:这更像是传递性而不是结合性。您不是第一个希望在Scala的隐式中使用它的人。另外,在您的第二行中,A -> C 可能是 B -> C 的笔误吗? - Travis Brown
3
请查看:如何在Scala中链接隐式转换? - Peter Schmitz
2个回答

9
似乎您在提问题时打错了字。您的意思是说你有从 A 到 B 和从 B 到 C 的隐式转换,但发现 A 到 C 的转换多余吗?Scala 有一个规则:必要时只应用一次隐式转换(但从不应用两次),所以您不能仅仅期望 Scala 自动组合 A 到 B 和 B 到 C 来实现您需要的转换。您需要提供自己的 A 到 C 转换。它并不是多余的。

4
这种情况的一个原因是可能存在中间类型的多个可能性。如果存在隐式转换 A -> B1B1 -> CA -> B2B2 -> C,编译器将无法猜测您想要哪一个。 - hammar
使用 implicit def transitive[A, B, C](implicit a2b: A => B, b2c: B => C): A => C = (a: A) => b2c(a2b(a)) 理论上可以进行传递式解析。但在这种情况下,每个 implicitly[A => B] 都会发散,因为存在隐式 $conforms[A]: A => A - 解析算法最终会陷入循环。 - phadej

6
似乎有些冗余,但是你应该提供 A -> C 转换。原因是如果隐式转换很少,那么传递链也很少,这可能是你想要的。但是如果隐式转换很常见,那么你可能能够将任何东西转换成任何东西(或者,如果你添加了一个方便的隐式转换,突然间所有行为都会改变,因为你开启了不同的隐式转换路径)。
但是,如果你指定要执行隐式转换的话,Scala 可以为你链接隐式转换。关键是使用带有 <% 的泛型,它表示“可以转换为”。以下是一个示例:
class Foo(i: Int) { def foo = i }
class Bar(s: String) { def bar = s }
class Okay(b: Boolean) { def okay = b }
implicit def to_bar_through_foo[T <% Foo](t: T) = new Bar((t: Foo).foo.toString)
implicit def to_okay_through_bar[U <% Bar](u: U) = new Okay((u: Bar).bar.length < 4)

scala> (new Foo(5)).okay
res0: Boolean = true

是的,我尝试了<%这件事,它起作用了。但是它还产生了一个奇怪的隐式从Array[String]=>Unit编译器错误。所以我回到手动跨越差距的方式了。谢谢你的帮助。 - Matei Alexandru Bogdan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接