2

私は 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)

}

私の問題は、このコードがコンパイルされないことです。workWithListObservableList[ListItem[Type1]]を期待するメソッドにObservableList[ListItem[Type1]] を使用できないと書かれています。

これで遊んでいると、このコードのいくつかのバリエーションは、チェックされていない警告があり、型消去のためにパターン マッチングが機能しないことを示しています。

理想的には:

  • タイプ ListItem[Type1] および ListItem[Type2] のオブジェクトを保持できるリストは 1 つだけです。
  • どのような種類のアイテムを扱うかによって異なることを行うために、アイテムを扱うときにパターン マッチングを行うことができます。
  • workWithItemどちらのタイプのアイテムでも機能します。私の現在のコードでは、署名を に変更してから実行するworkWithItem(item:ListItem[_])必要がありworkWithItem(someItem.asInstanceOf[ListItem[_]])ました。おそらく正しいことではありません!

ありがとう!

4

2 に答える 2

2

workWithList のメソッド シグネチャが間違っているようです -ListItemType型はどこから来たのですか? これはすべきdef workWithList(list: ObservableList[ListItem[_]]) { ...ですか?

その場合、一致ケースで遭遇する問題は、タイプの消去が原因で、JVM が実行時にケースのタイプ シグネチャ間の違いを認識できないことです。これは、たとえば、Type1、Type2、および ListItem をケース クラスに変換して (またはそれらの 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)

}

ObservableListFX ライブラリの特定の知識なしでここで作業していることに注意してください ( orではなく、ストレートなスカラ リストを使用してこれを試しましたFXCollections.observableArrayList)。したがって、これらはこのソリューションの適用可能性に影響を与える可能性があります (また、ListItemTypeが定義されている場所である可能性があります)。

workWithItem のメソッド シグネチャは問題ありませんが、asInstanceOf試したキャストは必要ありません。

于 2013-09-11T15:16:56.170 に答える
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)

}

エラーも警告もなく、同じリストに両方のタイプのオブジェクトを混在させることができます。

于 2014-06-25T07:08:14.800 に答える