实现接受多种类型的函数的最佳方法
Best way to implement a function that accepts multiple types
考虑到 scala 中没有 Union,
我有三个函数,它们接受不同的参数,但在其他方面完全相同。我怎样才能最好地实现这一点而不像现在这样重复自己?
import scala.sys.process._
def function1(command:String):String = {
...
command.!! // scala sys process execution
}
def function2(command:Seq[String]):String = {
...
command.!! // scala sys process execution
}
def function3(command:ProcessBuilder):String = {
...
command.!! // scala sys process execution
}
我不知道你为什么要在 String
上定义 !!
,所以我无法在这方面帮助你。但是假设您所做的只是使用 toString
。然后你的方法适用于任何支持 toString
的类型,这在 Scala 中几乎就是一切。所以只取 Any
.
def function(command: Any): String = {
// Do something with command.toString
}
如果您确实需要不同类型的不同案例,您可以使用 case classes 并根据不同类型进行调度。
sealed trait Foo
case class FooString(value: String)
case class FooSeq(value: Seq[String])
case class FooPB(value: ProcessBuilder)
def function(arg: Foo): String = {
arg match {
case FooString(str) => "It's a string!"
case FooSeq(str) => "It's a sequence!"
case FooPB(str) => "It's a process builder!"
}
}
由于您的特征是 sealed
,如果您忘记模式匹配中的任何情况,您将收到编译器警告。因此,您可以安全地处理每一个案例,并确信您已经做到了。
综上所述,如果你想支持多种类型,看看你想要的功能是否在一个通用的超类型中可用(在上面的例子中,Any
)。这可能是一个特征或 parent class。常见的候选者是 Seq
或 Iterable
。如果您需要基于 select 几种类型的不同行为,请定义一个密封特征和一些从它继承的 classes,这样您就可以对所有不同的可能性进行模式匹配。
有一个从 import scala.sys.process._
加载的隐式转换,它将从 String
和 Seq[String]
转换为 ProcessBuilder
,这使得执行 !
在这两种类型中,您可以使用相同的隐式转换来调用带有任何这些类型的 function3
import scala.sys.process._
function3(Seq(""))
function3("")
def function3(command:ProcessBuilder):String = {
...
command.!!
}
此代码应该可以编译,您不需要 function1
或 function2
。如果 import scala.sys.process._
不在 function2
调用的范围内,这将不起作用。
您可以在 scala.sys.process
中的包对象中找到隐式定义,如果您查看它,您会看到它正在扩展 ProcessImplicits
,它正在定义隐式转换
考虑到 scala 中没有 Union,
我有三个函数,它们接受不同的参数,但在其他方面完全相同。我怎样才能最好地实现这一点而不像现在这样重复自己?
import scala.sys.process._
def function1(command:String):String = {
...
command.!! // scala sys process execution
}
def function2(command:Seq[String]):String = {
...
command.!! // scala sys process execution
}
def function3(command:ProcessBuilder):String = {
...
command.!! // scala sys process execution
}
我不知道你为什么要在 String
上定义 !!
,所以我无法在这方面帮助你。但是假设您所做的只是使用 toString
。然后你的方法适用于任何支持 toString
的类型,这在 Scala 中几乎就是一切。所以只取 Any
.
def function(command: Any): String = {
// Do something with command.toString
}
如果您确实需要不同类型的不同案例,您可以使用 case classes 并根据不同类型进行调度。
sealed trait Foo
case class FooString(value: String)
case class FooSeq(value: Seq[String])
case class FooPB(value: ProcessBuilder)
def function(arg: Foo): String = {
arg match {
case FooString(str) => "It's a string!"
case FooSeq(str) => "It's a sequence!"
case FooPB(str) => "It's a process builder!"
}
}
由于您的特征是 sealed
,如果您忘记模式匹配中的任何情况,您将收到编译器警告。因此,您可以安全地处理每一个案例,并确信您已经做到了。
综上所述,如果你想支持多种类型,看看你想要的功能是否在一个通用的超类型中可用(在上面的例子中,Any
)。这可能是一个特征或 parent class。常见的候选者是 Seq
或 Iterable
。如果您需要基于 select 几种类型的不同行为,请定义一个密封特征和一些从它继承的 classes,这样您就可以对所有不同的可能性进行模式匹配。
有一个从 import scala.sys.process._
加载的隐式转换,它将从 String
和 Seq[String]
转换为 ProcessBuilder
,这使得执行 !
在这两种类型中,您可以使用相同的隐式转换来调用带有任何这些类型的 function3
import scala.sys.process._
function3(Seq(""))
function3("")
def function3(command:ProcessBuilder):String = {
...
command.!!
}
此代码应该可以编译,您不需要 function1
或 function2
。如果 import scala.sys.process._
不在 function2
调用的范围内,这将不起作用。
您可以在 scala.sys.process
中的包对象中找到隐式定义,如果您查看它,您会看到它正在扩展 ProcessImplicits
,它正在定义隐式转换