2012-03-13 54 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