2014-10-16 28 views
2

我有一個類型層次結構,並希望爲實現請求查找方法。我在遇到問題時無需使用asInstanceOf電話。在Scala中用TypeTag對類型層次結構進行模式匹配的習慣用法是什麼?

所以給人一種簡單的類型層次結構,像這樣

trait Vehicle 

trait Flying extends Vehicle 
class Plane extends Flying 

trait Driving extends Vehicle 
class Car extends Driving 

trait Swimming extends Vehicle 
class Boat extends Swimming 

我的查找方法是這樣的

def findVehicle[V <: Vehicle](implicit tag: TypeTag[V]): Option[V] = { 

    val v = tag.tpe match { 
    case t if t =:= typeOf[Flying] => Some(new Plane) 
    case t if t =:= typeOf[Driving] => Some(new Car) 
    case t if t =:= typeOf[Swimming] => Some(new Boat) 
    case _ => None 
    } 

    v.map(_.asInstanceOf[V]) 
} 

,象這樣

println(findVehicle[Flying]) // Some([email protected]) 

查找是否有可能實現像這樣的查找沒有asInstanceOf在最後?

回答

2

您可以避免使用TypeTag並改爲使用類型類。

trait Builder[+T] { 
    def build: Option[T] 
} 

implicit val flyingBuilder = new Builder[Flying] { 
    def build = Some(new Plane) 
} 

implicit val drivingBuilder = new Builder[Driving] { 
    def build = Some(new Car) 
} 

implicit val swimmingBuilder = new Builder[Swimming] { 
    def build = Some(new Boat) 
} 

implicit val anyBuilder = new Builder[Nothing] { 
    def build = None 
} 

def findVehicle[V <: Vehicle](implicit b: Builder[V]): Option[V] = b.build 

沒有反思,它肯定更習慣。

請注意,如何定義Builder[Nothing]通過返回None來重現您實現的相同行爲。這不一定是個好主意,因爲你現在被迫檢查該方法是否能夠產生價值。

我寧願一個編譯時錯誤,如果它是不可能建立所需類型的實例,您可以通過直接返回Tbuild反對Option[T]實現它(當然擺脫Nothing箱子的) 。

+0

這看起來很有希望,但是如何處理'case _ => None'情況? – 2014-10-16 16:39:43

+0

爲了使上面的註釋更加清楚:如果'flyingBuilder'沒有被定義,我們得到一個編譯錯誤,而不是'findVehicle'的'None'結果 – 2014-10-16 17:43:04

+0

我更新了我的答案。既然'Builder'是協變的,你可以簡單地用'build'來返回一個'Option [T]'並且在範圍內有一個'Builder [Nothing]。 – 2014-10-16 19:30:35

相關問題