我有一个类型层次结构,想要为实现请求一个查找方法。如果不求助于asInstanceOf
呼叫,我很难做到这一点。
所以给出一个简单的类型层次结构,比如
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(Plane@5b7fd935)
有可能在没有asInstanceOf
的情况下实现这样的查找吗?
您可以避免使用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
所实现的相同行为。这不一定是个好主意,因为您现在必须检查该方法是否能够产生值。
如果无法构建所需类型的实例,并且可以通过直接返回T
而不是从build
返回Option[T]
来实现,那么我更希望出现编译时错误(当然也可以去掉Nothing
的情况)。