这有点是一个理论问题,但我可能想做些什么。是否可以从Scala函数返回多个数据数据类型但限制允许的类型?我知道我可以通过指定它来返回一种类型,或者我基本上可以通过不指定返回类型来允许任何数据类型,但我想返回3种特定数据类型中的一种以保留一点类型安全性。有没有办法在返回类型中写'或',如:
def myFunc(input:String): [Int || String] = { ...}
主要的上下文是尝试编写通用数据加载脚本。我的一些用户使用Spark,一些Scalding,谁知道接下来会发生什么。我希望我的用户能够使用可能返回RichPipe,RDD或其他一些数据格式的通用加载脚本,具体取决于他们使用的框架,但我不想完全抛弃类型安全性。< / p>
答案 0 :(得分:8)
您可以使用Scala Library提供的Either类型。
def myFunc(input:String): Either[Int, String] = {
if (...)
Left(42) // return an Int
else
Right("Hello, world") // return a String
}
您可以通过嵌套使用两种以上的类型,例如Either[A,Either[B,C]]
。
答案 1 :(得分:1)
正如评论中已经提到的,你最好使用Either来完成这项任务,但是如果你真的想要它,你可以使用暗示
object IntOrString {
implicit def fromInt(i: Int): IntOrString = new IntOrString(None, Some(i))
implicit def fromString(s: String): IntOrString = new IntOrString(Some(s), None)
}
case class IntOrString(str: Option[String], int: Option[Int])
implicit def IntOrStringToInt(v: IntOrString): Int = v.int.get
implicit def IntOrStringToStr(v: IntOrString): String = v.str.get
def myFunc(input:String): IntOrString = {
if(input.isEmpty) {
1
} else {
"test"
}
}
val i: Int = myFunc("")
val s: String = myFunc("123")
//exception
val ex: Int = myFunc("123")
答案 2 :(得分:0)
我使用户的输入更少隐式和更明确。以下是三个例子:
def loadInt(input: String): Int = { ... }
def loadString(input: String): String = { ... }
那很好又简单。或者,我们可以使用一个函数,使用隐式上下文返回适当的curried函数:
def loader[T]()(implicit context: String): String => T = {
context match {
case "RDD" => loadInt _ // or loadString _
}
}
然后用户会:
implicit val context: String = "RDD" // simple example
val loader: String => Int = loader()
loader(input)
或者,可以将其转换为显式参数:
val loader: String => Int = loader("RDD")