鉴于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
}
答案 0 :(得分:3)
从import scala.sys.process._
加载的隐式转换会从String
和Seq[String]
转换为ProcessBuilder
,这样就可以执行!
在这两种类型中,您可以使用相同的隐式转换来调用任何这些类型的函数
import scala.sys.process._
function3(Seq(""))
function3("")
def function3(command:ProcessBuilder):String = {
...
command.!!
}
此代码应该编译,您不需要function1
或function2
。如果import scala.sys.process._
不在function2
CALL的范围内,这将无效。
您可以在scala.sys.process
中的包对象中找到隐式定义,如果您查看它,您会看到正在扩展ProcessImplicits
,这是定义隐式转换
答案 1 :(得分:1)
我不知道你为什么在!!
上定义了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
)。这可能是特质或父类。常见的候选人是Seq
或Iterable
。如果您需要基于少数几种类型的不同行为,请定义一个密封的特征和一些继承它的案例类,这样您就可以对所有不同的可能性进行模式匹配。