Possible ways to pass argument of different type t

2019-08-19 00:13发布

问题:

I want to group elements of different types into one.

Following is one example

trait Element

case class ElementString(key:String,value:String) extends Element
case class ElementDouble(key:String,value:Double) extends Element
case class ElementInt(key:String,value:Int) extends Element

Grp(ElementString("2","abc"),ElementDouble("3",100.20),ElementInt("4",10))
  • One possible way is to use varargs case class Grp(group:Element*).

    Is there any other efficient way to achieve the above . Any possible way to add elements one by one into Grp

Updated

I would also like to create a Group inside a Group.

回答1:

A DSL like this is very common in scala because it is type-safe, but also very concise to use:

trait Value

object Value {
  case class StringValue(value: String) extends Value
  case class DoubleValue(value: Double) extends Value
  case class IntValue(value: Int) extends Value
}

case class Element(key: String, value: Value)
object Element {
  implicit def fromStringPair (a: (String,String)) = Element(a._1, Value.StringValue(a._2))
  implicit def fromDoublePair (a: (String,Double)) = Element(a._1, Value.DoubleValue(a._2))
  implicit def fromIntPair (a: (String,Int)) = Element(a._1, Value.IntValue(a._2))
}

case class Grp (elements: Element*)

Grp(
  "2" -> "abc",
  "3" -> 100.20,
  "4" -> 10
)

//: Grp = Grp(WrappedArray(Element(2,StringValue(abc)), Element(3,DoubleValue(100.2)), Element(4,IntValue(10))))

Alternative, no varargs:

trait Value

// define these in different files if you want
case class Student(value: String) extends Value
case class Employee(value: Double) extends Value
case class Department(value: Int) extends Value

case class Element(key: String, value: Value)

case class Grp (elements: List[Element] = Nil) extends Value {
  def add (key: String, value: Value): Grp = Grp(this.elements ++ List(Element(key, value)))
}

Grp()
  .add("2", Student("abc"))
  .add("3", Employee(100.20))
  .add("4", Department(10))
  .add("5", Grp().add("2", Student("xyz"))) // nested group


回答2:

You can use a quasi builder pattern by adding the a function:

def withElement(elem: Element) = copy(group = group :+ elem)

Assuming group is a list. Note that this does make a new copy of the case class each time you call withElement. The code would then look like:

Grp().withElement(...).withElement(...)

You could create a real builder pattern if performance was important.