【发布时间】:2016-08-11 16:48:37
【问题描述】:
我想创建一个 scala 方法参数类型,它是多种类型的集合,这些类型都可以转换为常见的给定类型,但我无法使用隐式转换、类型类、上下文边界和视图来做到这一点界限。
我创建了一个 trait 和扩展该 trait 的类,我想编写一个方法,允许其他开发人员传入我的代码将处理的实例集合。但是,我不希望我的方法的调用者创建实例集合。相反,我希望调用者传入一个元组集合,其中元组必须来自一组已定义的元组。
trait 和 case 类如下所示:
sealed trait Widget {
type W
def identifier: W
def number: Int
}
case class CWidget(identifier: Char, number: Int) extends Widget {type W = Char}
case class SWidget(identifier: String, number: Int) extends Widget {type W = String}
case class CSWidget(identifier: (Char, String), number: Int) extends Widget {type W = (Char, String)}
方法如下所示:
def getWidgets[W <% Widget](s: Seq[W]): Unit = ...
目前,允许的元组将具有以下类型:(Char, Int)、(String, Int) 和 (Char, String, Int)。最终,我希望能够允许像 (Int, Char) 这样混淆顺序的元组,但那是另一回事了。
我创建了这些隐式方法并使用import 将它们带入范围:
implicit def fromTuple(t: (Char, Int)) = ((c: Char, n: Int) => CWidget(c, n)) tupled t
implicit def fromTuple(t: (String, Int)) = ((s: String, n:Int) => SWidget(s, n)) tupled t
implicit def fromTuple(t: (Char, String, Int)) = ((c: Char, s: String, n: Int) => CSWidget((c, s), n)) tupled t
我从 REPL 中尝试过这个:
getWidgets(Seq(('a',1),("string",2),('c',"string",3)))
并收到此错误:
<console>:26: error: No implicit view available from Product with Serializable => Widget.
提前致谢!
已编辑:
这是执行答案的结果(谢谢,@gregghz!):
sealed trait Widget {
type W
def identifier: W
def number: Int
}
case class CWidget(identifier: Char, number: Int) extends Widget {type W = Char}
case class SWidget(identifier: String, number: Int) extends Widget {type W = String}
case class CSWidget(identifier: (Char, String), number: Int) extends Widget {type W = (Char, String)}
implicit def fromTupleCI(t: (Char, Int)): Widget = {
val (c, n) = t
CWidget(c, n)
}
implicit def fromTupleSI(t: (String, Int)): Widget = {
val (s, n) = t
SWidget(s, n)
}
implicit def fromTupleCSI(t: (Char, String, Int)): Widget = {
val (c, s, n) = t
CSWidget((c, s), n)
}
def getWidgets(s: Widget*): Unit = {
s.foreach { w => println(w) }
}
getWidgets(('a',1), ('b',2), ('c', "abc", 3), ("abcd", 4)
结果如下:
CWidget(a,1)
CWidget(b,2)
CSWidget((c,abc),3)
SWidget(abcd,4)
这很好,因为我不想强迫调用者为 getWidgets 方法创建一个 Seq。
最重要的是,它会在编译时检查参数的类型(感谢静态类型!)。我本可以将 getWidgets 参数设为 Any 并使用模式匹配,但这会检查参数是否运行时。
【问题讨论】:
标签: scala collections types implicit-conversion