如何在Scala中创建通用案例类列表?

时间:2017-12-18 21:44:28

标签: scala generics

在我的网络应用中,用户将不同类型的数据上传到我们的服务器:string,excel文件,整数。如果可能,我想将所有这些数据汇总到一个列表中:

object CacheII extends App{
  case class Data[TypeT](kind: String, data: TypeT)

  val item1 = Data("type1", "data1")
  val item2 = Data("type1", "data2")
  val item3 = Data("type2", "data1".getBytes())
  val item4 = Data("type2", "data2".getBytes())

  val list = List(item1, item2, item3, item4)

  val item5 = if(true)
    Data("type2", "data1".getBytes())
  else if(true)
    Data("type1", "data1")
  else
    Data("type3", 548)

  def addItem(list: List[Data[Any]], item: Data[Any]) = {
    list :+ item
  }

  println(addItem(list, item5))
}

编译器错误:

Error:(22, 19) type mismatch;
 found   : List[CacheII.Data[_ >: Array[Byte] with String <: java.io.Serializable]]
 required: List[CacheII.Data[Any]]
  println(addItem(list, item5))
                  ^

如何正确创建这样的用户数据列表? 是否有不同/更好的方法来做到这一点?

感谢任何建议。

谢谢。

2 个答案:

答案 0 :(得分:3)

您可以使用协变TypeT创建列表。但解决此问题的一般方法是使用ADT

sealed trait Data

case class StringData(value: String) extends Data

case class ByteData(value: Array[Byte]) extends Data

依旧......

优势

  1. 模式匹配提取。

  2. 错过某些案例时编译错误/警告。

  3. 不易出错

  4. 自动完成支持以从IntelliJ构思和其他IDE生成所有案例

  5. 优雅

  6. Scala REPL

    将不同的新数据项添加到旧列表

    scala> :paste
    // Entering paste mode (ctrl-D to finish)
    
        sealed trait Data
    
        case class StringData(value: String) extends Data
    
        case class ByteData(value: Array[Byte]) extends Data
    
    // Exiting paste mode, now interpreting.
    
    defined trait Data
    defined class StringData
    defined class ByteData
    
    scala> val oldList = List(StringData("stackoverflow"), ByteData("scala".getBytes))
    oldList: List[Product with Serializable with Data] = List(StringData(stackoverflow), ByteData([B@108b121f))
    
    scala> def addItem(oldList: List[Data], newItem: Data): List[Data] = oldList ++ List(newItem)
    addItem: (oldList: List[Data], newItem: Data)List[Data]
    
    scala> addItem(oldList, StringData("cow goes moo"))
    res1: List[Data] = List(StringData(stackoverflow), ByteData([B@108b121f), StringData(cow goes moo))
    

答案 1 :(得分:0)

简单地使数据协变:

case class Data[+TypeT](kind: String, data: TypeT)

您可以在https://docs.scala-lang.org/tour/variances.html

了解有关差异的更多信息