2013-10-11 107 views
1

我真的ambigous类型在Scala中挣扎......与ambigous类型挣扎在斯卡拉

我想实现一个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:斯卡拉版本2.9.2

+0

Scala使用类型擦除,所以你不能写'Some(stack:mutable.Stack [T])',你应该使用'Some( stack:mutable.Stack [_])'而不是 – crybird

+0

如果你的stacks.get(id)匹配匹配现有的不同类型的堆栈(不是T),你会怎么做? – Ashalynd

回答

1

有一个解决方案,但它有点过分。 (引自斯卡拉低于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中试过。

+0

对不起,但你明显误解我:( 我不需要在ID混合类型为堆栈HashMap的关键问题mutable.Stack [_]是我得到一个“未绑定的通配符类型错误。Scala版本是2.9.2 – kitingChris

+0

我刚刚编辑了我的答案,看到下一个变体似乎更接近你想要什么。 – Ashalynd

+0

非常感谢:) – kitingChris

1

因为类型参数并不存储在执行阶在JVM上,如果需要,您需要自己存储这些类型。例如,

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

,然后检查是否是Class等于要求什么。
但这可能不是你想要的:堆栈将被不同类型的堆栈覆盖。但是你明白了,可以发明一些有用的东西。

+0

好吧,看起来更奇怪....:D 其实我想使用StackManager.set [ClassA](“stack01”,新mutable.Stack [ClassA])''以及'StackManager.set [ClassB] (“stack02”,新的mutable.Stack [ClassB])' 换句话说,我想存储不同类型的堆栈... – kitingChris

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的某种类型检查会很好...