我正在使用ScalaFX和JavaFX,并拥有以下代码:
import scalafx.Includes._
class Type1(anInt: Int, ...)
class Type2(aString: String, ...)
class ListItem[T](internalValue:T, ...)
object Worker
{
val list1 = FXCollections.observableArrayList[ListItem[Type1]]()
val list2 = FXCollections.observableArrayList[ListItem[Type2]]()
def workWithList(list:ObservableList[ListItemType]) {
list.foreach(i => workWithItem(i))
}
def workWithItem(item:ListItem) {
item match {
case i:ListItem[Type1] => do something
case i:ListItem[Type2] => do something else
}
}
workWithList(list1)
workWithList(list2)
}
我的问题是这段代码没有编译;它说我不能使用ObservableList [ListItem [Type1]]作为workWithList
方法,它需要ObservableList [ListItem]。
正如我一直在玩这个,此代码的一些变体表示存在未经检查的警告,并且由于类型擦除,模式匹配将不起作用。
理想情况下:
workWithItem
可以使用任何一种类型的项目。在我当前的代码中,我必须将签名更改为workWithItem(item:ListItem[_])
,然后执行workWithItem(someItem.asInstanceOf[ListItem[_]])
。可能不是正确的事情!谢谢!
答案 0 :(得分:2)
import scalafx.Includes._
import javafx.collections.{FXCollections,ObservableList}
class ListItemType
class Type1(anInt: Int) extends ListItemType
class Type2(aString: String) extends ListItemType
class ListItem(val internalValue:ListItemType)
object Worker
{
val list1 = FXCollections.observableArrayList[ListItem]()
val list2 = FXCollections.observableArrayList[ListItem]()
def workWithList(list:ObservableList[ListItem]) {
list.foreach(i => workWithItem(i))
}
def workWithItem(item:ListItem) {
item.internalValue match {
case i:Type1 => println("do something")
case i:Type2 => println("do something else")
}
}
workWithList(list1)
workWithList(list2)
}
没有错误,没有警告,您可以在同一个列表中混合使用这两种类型的对象。
答案 1 :(得分:1)
workWithList的方法签名看起来不对 - ListItemType
类型来自哪里?这应该是def workWithList(list: ObservableList[ListItem[_]]) { ...
吗?
如果是这样,那么在匹配情况下遇到的问题是由于类型擦除,JVM无法在运行时区分案例的类型签名。这可以解决,例如,将Type1,Type2和ListItem转换为case类(或手动为它们生成unapply方法),然后在匹配的情况下解构项,如下所示:
case class Type1(anInt: Int)
case class Type2(aString: String)
case class ListItem[T](internalValue:T)
object Worker
{
val list1 = FXCollections.observableArrayList[ListItem[Type1]]()
val list2 = FXCollections.observableArrayList[ListItem[Type2]]()
def workWithList(list: ObservableList[ListItem[_]]) {
list.foreach(i => workWithItem(i))
}
def workWithItem(item: ListItem[_]) {
item match {
case ListItem(i: Type1) => println(s"Have type 1: ${i.anInt}") //do something
case ListItem(i: Type2) => println(s"Have type 2: ${i.aString}") //do something else
case anythingElse => println(s"Unknown type: $anythingElse") //just as a safe default for now
}
}
workWithList(list1)
workWithList(list2)
}
请注意,我在这里工作时没有FX库的特定知识(我尝试使用直接scala列表而不是ObservableList
或FXCollections.observableArrayList
),因此它们可能会影响此解决方案的适用性(和可能是定义ListItemType
的地方。
workWithItem的方法签名很好,但不应该要求你尝试的asInstanceOf
强制转换。