我真的在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 version 2.9.2
答案 0 :(得分:1)
因为在JVM上执行scala时不存储类型参数,所以如果需要,您需要自己存储这些类型。例如,
val stacks = mutable.HashMap[String, (Class, mutable.Stack[_])]()
然后检查Class
是否等于请求的内容
但这可能不是你想要的:堆栈将被不同类型的堆栈覆盖。但你得到了这个想法,并且可以创造出有效的东西。
答案 1 :(得分: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中尝试过它。
答案 2 :(得分: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会很棒...