2012-03-13 58 views
3

我有一些問題,捕捉一個ClassCastException。 它在檢索函數的模式匹配的最後一種情況下發生,例外情況並非如此。不能趕上ClassCastException異常Scala的

我該如何解決這個問題?

abstract class Property 

    object EmptyProperty extends Property 

    class PropertyCompanion[T] 

    object Type extends PropertyCompanion[Type] 
    case class Type extends Property 

    object Name extends PropertyCompanion[Name] 
    case class Name extends Property 

    abstract class Entity { 
    protected val properties: Map[PropertyCompanion[_], Property] 
    def retrieve[T](key: PropertyCompanion[T]) = 
     properties.get(key) match { 
     case Some(x) => x match { 
      case EmptyProperty => throw new Exception("empty property") 
      case _ => { 
      try { 
       x.asInstanceOf[T] 
      } catch { 
       case e => throw new Exception("fubar") 
      } 
      } 
     } 
     case None => throw new Exception("not found") 
     } 
    } 

    case class Book(protected val properties: Map[PropertyCompanion[_], Property]) extends Entity { 
    def getType = retrieve(Type) 
    def getName = retrieve(Name) 
    } 

    object Test extends App { 

    val book = Book(Map(Type -> Type(), Name -> Type())) 
    val name = book.getName 
    } 

回答

5

不能捕獲異常,因爲你無法投射到T的JVM運行時並不知道T,所以你要欺騙有點;-)。將implicit m: CLassManifest[T]傳遞給您的方法並使用m.erasure.cast(x)。你可能是這樣的:

abstract class Property 

object EmptyProperty extends Property 

class PropertyCompanion[T] 

object Type extends PropertyCompanion[Type] 
case class Type extends Property 

object Name extends PropertyCompanion[Name] 
case class Name extends Property 

abstract class Entity { 
    protected val properties: Map[PropertyCompanion[_], Property] 
    def retrieve[T](key: PropertyCompanion[T])(implicit m: ClassManifest[T]) = 
    properties.get(key) match { 
     case Some(x) => x match { 
     case EmptyProperty => throw new Exception("empty property") 
     case _ => { 
      try { 
      m.erasure.cast(x).asInstanceOf[T] 
      } catch { 
      case e => throw new Exception("fubar") 
      } 
     } 
     } 
     case None => throw new Exception("not found") 
    } 
} 

case class Book(protected val properties: Map[PropertyCompanion[_], Property]) extends Entity { 
    def getType = retrieve(Type) 
    def getName = retrieve(Name) 
} 

object Test extends App { 

    val book = Book(Map(Type -> Type(), Name -> Type())) 
    val name = book.getName 
} 

編輯:增加了投至T,以獲得正確的返回類型

+0

非常感謝。所以沒有使用Manifest就沒有辦法呢?它會帶來性能成本嗎? – roelio 2012-03-13 21:46:23

+0

我也還是要回到'result.asInstanceOf [T]'因爲否則返回'Any'型 – roelio 2012-03-13 21:49:51

+0

你說得對,我看到相同的行爲,這很奇怪,因爲Javadoc文檔'類[T]'秀這個表示法:'T cast(Object obj)'。我不認爲有另一種方式,因爲這是scala如何欺騙類型刪除。除了額外的對象分配之外,不應該有更多的性能成本。 – drexin 2012-03-13 22:25:35