2015-10-05 50 views
0

我实际上正在尝试创建一个可以表示列中表格数据的类。这是我正在编写的代码的简化模型,旨在说明令我困惑的关于scala类型的内容。如何定义可接受List [List [String]]和List [List [Int]]作为输入的案例类?

比方说,我有两种类型

case class FunnyColumn[T](data:List[T]) 
case class FunnyTable(items:List[FunnyColumn[Any]]) 

我要开始添加的东西对我FunnyTable,所以这里去。我做了一堆列,我可能要添加:

val intItem:FunnyColumn[Int] = new FunnyColumn(List(1,2,3)) 
val stringItem:FunnyColumn[String] = new FunnyColumn(List("A", "B", "C")) 
val untypedItem:FunnyColumn[Any] = new FunnyColumn(List(1,2,3)) 

到目前为止好:

// works but seems icky, untyped FunnyColumns are not much use to me! 
val funny0 = new FunnyTable(List(untypedItem)) 

我真的不希望我的专栏是类型化的 - 我想我所有的列有意义的类型。在这个例子中,我已经试过(但失败了)加FunnyColumn [字符串]:

// Fails because it wants List[FunnyColumn[Any]] but I gave it List[FunnyColumn[Int]] 
val funny1 = new FunnyTable(List(intItem)) 

这个问题似乎是因为我定义为FunnyTable接受字面上List[FunnyColumn[Any]],所以比Any列表以外的任何键入的FunnyColumns绑定失败。

我想要做的就是就是让这个我可以把任何FunnyColumn的变化到我FunnyTable,换句话说,这也应该工作:

// Fails because it wants List[FunnyColumn[Any]] but I gave it List[FunnyColumn[_ :> String with Int]] 
val funny2 = new FunnyTable(List(intItem, stringItem)) 

我如何重新定义我的FunnyTable类这样我可以在其中存储不同的FunnyColumn子类型?

回答

1

你需要让FunnyColumn协在T

case class FunnyColumn[+T](data:List[T]) 

然后FunnyColumn[Any]FunnyColumn[Int]的超类型。

+0

这似乎是伎俩。有没有一些参考资料可以解释这个强大的魔法究竟是如何工作的? –

+0

@SalimFadhley - 你可能会发现这个[scala school](https://twitter.github.io/scala_school/type-basics.html#variance)页有帮助。基本上,对于某些泛型类型的构造函数'F',即使A是B的超类型,F [A]也不会自动成为F [B]的超类型。 'FunnyColumn'上的协方差注释'+ T'使得你想要的列的关系。 – Lee

+0

“那么FunnyColumn [Any]是FunnyColumn [Int]的子类型 - 当然你的意思是相反,FunnyColumn [Int]必须是FunnyColumn [Any]的子类型? –