假设我有一个隐式转换:
implicit def aToB(a: A):B={
...
}
如何让这种隐式转换适用于列表的元素?
如果我有:
val listOfA: List[A] ...
我有一个接受 B 列表的函数,是否可以让 Scala 将所有元素从 A 隐式转换为 B?
如果没有隐式转换,转换可能如下所示:
lisftOfA.map(a => new B(a.someValue, a.anotherValue))
但我希望这能像“魔法”一样发生……这个要求是否太过分了。
最佳答案
以下是您可能希望考虑的一些替代方案:
<强>1。使用 View 绑定(bind)
如果可以更改采用 B 列表的函数,这将是最简单的解决方案。修改它以接受可以转换为 B 的事物列表。也就是说,
def yourFn(l: List[B]) = ...
会变成
def yourFn[X <% B](l: List[X]) = ...
然后,您可以使用 listOfA 调用该函数:
yourFn(listOfA)
<强>2。介绍一下转换方法
这与 Rogach 的第一个解决方案类似,只是外部转换是非隐式的:
def convert[B, A <% B](l: List[A]): List[B] = l map { a => a: B }
然后在函数的调用站点,您可以编写
yourFn(convert(listOfA))
与 Rogach 的第二个解决方案一样,这比引入隐式转换要安全一些。
<强>3。引入隐式转换
这相当于 Rogach 的第一个解决方案,但符号更好一点(IMO)。
implicit def convert[B, A <% B](l: List[A]): List[B] = l map { a => a: B }
如果此转换在您的调用站点范围内,您只需使用 listOfA 调用您的函数即可:
yourFn(listOfA)
离别的思念
考虑如何以通用的方式解决这个问题是很有趣的。如果我想定义我的转换方法,以便它可以处理实现 map
方法的任何类型,该怎么办?即,
def convert[B, A <% B, C[_]](c: C[A]): C[B] = c map { a => a: B }
这当然行不通,因为签名中没有任何内容表达 C
必须实现 map
的约束。据我所知,表达这个约束是相当复杂的,并且不能通过为任何实现 map
的类型提供开箱即用的支持的方式来完成。请参阅Type-safe Scala sequence comprehensions .
关于scala - 如何在集合中进行隐式转换?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12447968/