解決策はありますが、少し不安定です。(簡単なデモとして、以下の 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 では試していません。