Reputation: 777
In my web app, a user uploads different kinds of data to our server: string, excel files, ints. I want to assemble all this data in one list if possible:
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))
}
Compiler Error:
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))
^
How to correctly create such a list of the user data? Is there a different/better way to do this?
Any advice is appreciated.
Thank you.
Upvotes: 1
Views: 1960
Reputation: 14825
You can create a list using covariant TypeT
. But general way to approach this problem is using ADTs
sealed trait Data
case class StringData(value: String) extends Data
case class ByteData(value: Array[Byte]) extends Data
and so on ....
Pattern matching extraction.
Compiler error/warning when certain case is missed.
Less error prone
Auto complete support to generate all cases from IntelliJ idea and other IDEs
Elegant
Adding different new data items to old list
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))
Upvotes: 3
Reputation: 18424
Simply make Data covariant:
case class Data[+TypeT](kind: String, data: TypeT)
You can read more about variances at https://docs.scala-lang.org/tour/variances.html
Upvotes: 0