Reputation: 1011
Given that there's no Union in scala,
I have a three functions that accept different parameters, but are otherwise exactly the same. How would I best implement this without repeating myself like I do now?
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
}
Upvotes: 0
Views: 681
Reputation: 3863
There is an implicit conversion loaded from import scala.sys.process._
that will convert from String
and Seq[String]
to ProcessBuilder
, that is what is making possible to execute the !
in those 2 types, you can use that same implicit conversion to call function3 with any of those types
import scala.sys.process._
function3(Seq(""))
function3("")
def function3(command:ProcessBuilder):String = {
...
command.!!
}
this code should compile, you dont need function1
or function2
. THIS WILL NOT WORK IF import scala.sys.process._
IS NOT IN THE SCOPE OF THE function2
CALL.
You can find the implicit definitions in the package object in scala.sys.process
, if you look at it you will see that is extending ProcessImplicits
which is defining the implicit conversions
Upvotes: 3
Reputation: 70287
I have no idea why you have !!
defined on String
, so I can't help you there. But let's say all you do is use toString
. Then your method works on any type which supports toString
, which in Scala is literally everything. So just take Any
.
def function(command: Any): String = {
// Do something with command.toString
}
If you actually do need different cases for different types, you can use case classes and dispatch based on the different types.
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!"
}
}
Since your trait is sealed
, you'll get a compiler warning if you forget any cases in the pattern match. Thus, you can safely handle every case and be confident you have done so.
In summary, if you want to support multiple types, see if the functionality you desire is available in a common supertype (in the above example, Any
). This could be a trait or a parent class. Common candidates for this are Seq
or Iterable
. If you need different behavior based on a select few types, define a sealed trait and some case classes that inherit from it, so you can pattern match on all the different possibilities.
Upvotes: 1