2011-06-06 68 views
1

我要實現以下詳盡的比賽固定一個匹配這條警告,但我無法弄清楚刪除類型參數,因此警告說,這將被刪除:通過擺脫一個類型參數

sealed trait Q[+V] 
case object QEmpty extends Q[Nothing] 
sealed trait QNonEmpty[V] extends Q[V] { 
    def foo: V 
} 
final class QLeaf[V](val foo: V) extends QNonEmpty[V] 
final class QNode[V](val foo: V, var children: Array[Q[V]]) extends QNonEmpty[V] 

def test[V](n: Q[V]): String = n match { 
    case QEmpty   => "empty" 
    case n: QNonEmpty[V] => n.foo.toString // warning: type parameter V is erased 
} 

在我的具體情況case n比賽的身體是非常大的,而且我不希望增加更多的比賽子句,這樣我反而對陣QLeafQNode(因爲在我的具體情況下,有兩個以上的子類,還他們是可變的,因此不應該是案例類)。解析類型需要爲QNonEmpty[V],不能是QNonEmpty[_]

我可以爲QNonEmpty創建一個與QLeafQNode匹配的提取器嗎?

+0

附:沒有任何體現;這是一個性能關鍵的位,所以請不要額外的對象創建像'特性Q [+ V] {def lift:'[QEmpty,QNonEmpty [V]]}' – 2011-06-06 23:45:06

+0

編寫這樣一個提取器的唯一方法是使用isInstanceOf和具體類型。我想你知道該怎麼做? – 2011-06-07 06:22:35

+0

@金艾姆,不,但我已經寫了幾個簡單的提取器,所以一定能弄明白。可惜無法完成類型安全 – 2011-06-07 07:24:29

回答

3

可以使用存在的類型匹配的類型與刪除參數:

type AnyNonEmpty = QNonEmpty[X] forSome { type X } 

in match { 
    case x: AnyNonEmpty => //... 
} 

的提取看起來是這樣的:

object QNonEmpty { 
    def unapply(in: QNonEmpty[_]): Option[Any] = Some(in.foo) 
} 

def test[ V ](n: Q[ V ]) : String = n match { 
    case QEmpty => "empty" 
    case QNonEmpty(foo) => foo.toString 
} 

我不認爲你可以寫一個類型安全但是,在您的示例代碼中,該方法的類型參數也會被刪除。 也許你應該考慮增加一個fold方法的特點和重寫你這樣的例子:

sealed trait Q[ +V ] { 
    def fold[A](e: => A, f: V => A): A = e 
} 

case object QEmpty extends Q[ Nothing ] 

sealed trait QNonEmpty[ V ] extends Q[ V ] { 
    def foo: V 
    override def fold[A](e: => A, f: V => A) = f(foo) 
} 

// ... 

def test[V](n: Q[V]) = n.fold("empty", _.toString) 
+0

謝謝。我有點像'fold'方法。在我的情況下,我完全控制'Q',所以添加這個沒問題。 (我仍然想知道如果'Q'來自外部庫,我會怎麼做)。 – 2011-06-07 07:23:06