Instantiating a case class from a list of parameters

后端 未结 4 1505
春和景丽
春和景丽 2020-12-02 07:27

Given:

case class Foo(a: Int, b: String, c: Double)

you can say:

val params = Foo(1, \"bar\", 3.14).productIterator.toList
         


        
相关标签:
4条回答
  • 2020-12-02 08:04
    scala> case class Foo(a: Int, b: String, c: Double)
    defined class Foo
    
    scala> val params = Foo(1, "bar", 3.14).productIterator.toList
    params: List[Any] = List(1, bar, 3.14)
    
    scala> Foo.getClass.getMethods.find(x => x.getName == "apply" && x.isBridge).get.invoke(Foo, params map (_.asInstanceOf[AnyRef]): _*).asInstanceOf[Foo]
    res0: Foo = Foo(1,bar,3.14)
    
    scala> Foo(1, "bar", 3.14) == res0
    res1: Boolean = true
    

    Edit: by the way, the syntax so far only being danced around for supplying the tuple as an argument is:

    scala> case class Foo(a: Int, b: String, c: Double)
    defined class Foo
    
    scala> Foo.tupled((1, "bar", 3.14))                
    res0: Foo = Foo(1,bar,3.14)
    
    0 讨论(0)
  • 2020-12-02 08:11

    You could use pattern matching like:

    params match {                                   
     case List(x:Int, y:String, d:Double) => Foo(x,y,d)
    }
    
    0 讨论(0)
  • 2020-12-02 08:16

    Well, you can certainly do this with a tuple:

    (Foo _).tupled apply (1, bar, 3.14)
    

    But there is no real way to get from a List[S] to (A, B, C) for A, B, C <: S. There may be a way of doing this with HLists of course

    0 讨论(0)
  • 2020-12-02 08:27

    Another one liner using case class companion object curried method and completely ignoring type safety :)

    scala> case class Foo(a: Int, b: String, c: Double)
    defined class Foo
    
    scala> val lst = List(1, "bar", 3.14)
    lst: List[Any] = List(1, bar, 3.14)
    
    scala> val foo = lst.foldLeft(Foo.curried: Any){case (r, v) => r.asInstanceOf[Function[Any, _]](v) }.asInstanceOf[Foo]
    foo: Foo = Foo(1,bar,3.14)
    
    0 讨论(0)
提交回复
热议问题