1

私はscalaのあいまいな型に本当に苦労しています...

タイプの異なる複数のスタックを保持する StackManager を実装したいのですが、何かがおかしいようです。

object StackManager {

  val stacks = mutable.HashMap[String, mutable.Stack[_]]()
  def get[T](id: String): mutable.Stack[T] = {
    stacks.get(id) match {
      case Some(stack: mutable.Stack[T]) => stack
      case None => {
        val newStack = mutable.Stack[T]()
        stacks.put(id, newStack)
        newStack
      }
    }
  }
  def set[T](id: String, stack: mutable.Stack[T]) {
    stacks.put(id, stack)
  }
}

編集:それで、マネージャーにさまざまなタイプのスタックを保存したい:

StackManager.set[ClassA]("stack01", new mutable.Stack[ClassA]())
StackManager.set[ClassB]("stack02", new mutable.Stack[ClassB]())

StackManager.get[ClassA]("stack01") // returns the stack with type mutable.Stack[ClassA]
StackManager.get[ClassB]("stack02") // returns the stack with type mutable.Stack[ClassB]

EDIT2: scala バージョン 2.9.2

4

3 に答える 3

1

解決策はありますが、少し不安定です。(簡単なデモとして、以下の Scala 2.10 コンソールからの出力を引用します)

import scala.reflect.runtime.{universe=>ru}
import scala.collection.mutable

scala> :paste
// Entering paste mode (ctrl-D to finish)

object StackManager {

  val stacks = mutable.HashMap[(String, ru.Type), mutable.Stack[_]]()
  def get[T:ru.TypeTag](id: String): mutable.Stack[T] = {
    stacks.get((id,ru.typeOf[T])) match {
      case Some(stack: mutable.Stack[T]) => stack
      case _ => {
        val newStack = mutable.Stack[T]()
        stacks.put((id,ru.typeOf[T]), newStack)
        newStack
      }
    }
  }
  def set[T:ru.TypeTag](id: String, stack: mutable.Stack[T]) {
    stacks.put((id,ru.typeOf[T]), stack)
  }
}


// Exiting paste mode, now interpreting.

defined module StackManager

scala> StackManager.set("example", new mutable.Stack[String])

scala> StackManager.set("example", new mutable.Stack[Int])

scala> StackManager.get[Int]("example")
res15: scala.collection.mutable.Stack[Int] = Stack()

scala> StackManager.get[String]("example")
res16: scala.collection.mutable.Stack[String] = Stack()

scala> StackManager.get[Double]("example")
res17: scala.collection.mutable.Stack[Double] = Stack()

タイプタグのない、ファンキーではないソリューション:

object StackManager {

  val stacks = mutable.HashMap[String, mutable.Stack[_ <:Any]]()
  def get[T](id: String): mutable.Stack[T] = {
    stacks.get(id) match {
      case Some(stack: mutable.Stack[_]) => stack.asInstanceOf[mutable.Stack[T]]
      case _ => {
        val newStack = mutable.Stack[T]()
        stacks.put(id,newStack)
        newStack
      }
    }
  }
  def set[T](id: String, stack: mutable.Stack[T]) {
    stacks.put(id,stack)
  }
}

そして、型チェックも行うようです:

scala> StackManager.set[String]("string",new mutable.Stack[String])

scala> StackManager.set[Integer]("integer",new mutable.Stack[String])
<console>:11: error: type mismatch;
 found   : scala.collection.mutable.Stack[String]
 required: scala.collection.mutable.Stack[Integer]
              StackManager.set[Integer]("integer",new mutable.Stack[String])

scala> StackManager.set[Integer]("integer",new mutable.Stack[Integer])

scala> StackManager.get[Integer]("integer")
res11: scala.collection.mutable.Stack[Integer] = Stack()

ただし、scala 2.9 では試していません。

于 2013-10-12T20:38:31.720 に答える
1

JVM で scala を実行している間は型パラメーターが保存されないため、必要に応じてその型を自分で保存する必要があります。例えば、

val stacks = mutable.HashMap[String, (Class, mutable.Stack[_])]()

それClassが要求されたものと等しいかどうかを確認します。
しかし、これはおそらくあなたが望むものではありません: スタックは異なるタイプのスタックで上書きされます。しかし、あなたはアイデアを得て、機能するものを発明することができます.

于 2013-10-11T05:40:22.363 に答える
0

適切な解決策を見つけました:

object StackManager {

  val stacks = mutable.HashMap[String, S forSome {type S}]()
  def get[S](id: String): S = {
    stacks.get(id) match {
      case Some(stack) => stack.asInstanceOf[S]
      case None => null.asInstanceOf[S]
    }
  }
  def set[S](id: String, stack: S) {
    stacks.put(id, stack)
  }
}


StackManager.set[mutable.Stack[ClassA]]("stack01", new mutable.Stack[ClassA]())
StackManager.set[mutable.Stack[ClassB]]("stack02", new mutable.Stack[ClassB]())

StackManager.get[mutable.Stack[ClassA]]("stack01") // returns the stack with type mutable.Stack[ClassA]
StackManager.get[mutable.Stack[ClassB]]("stack02") // returns the stack with type mutable.Stack[ClassB]

改善のアイデアはありますか?mutable.Stack のある種の型チェックは素晴らしいでしょう...

于 2013-10-12T22:43:30.730 に答える