2013-10-11 106 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的某種類型檢查會很好...