我想有一个方法返回某个类的类,但我希望该方法的行为不同,具体取决于类是否扩展特定的特征,如下所示:
case class ClassA extends TraitA
case class ClassB extends TraitB
case class ClassC extends TraitA
...
def myfunc[T]():T = {
T match {
case TraitA => // return new T in a particular way
case TraitB => // ditto
}
}
这是可能的,还是我以错误的方式去做?
谢谢
Rex*_*err 15
您不能直接比较类型,因为没有任何可比较的东西(在运行时,由于擦除).你可以处理你的班级的代表:
trait TraitA { }
trait TraitB { }
class ClassA extends TraitA { }
class ClassB extends TraitB { }
def myFunc[T](clazz: Class[T]) = {
if (classOf[TraitA] isAssignableFrom clazz) println("A")
else if (classOf[TraitB] isAssignableFrom clazz) println("B")
else println("?")
}
scala> myFunc(classOf[ClassA])
A
scala> myFunc(classOf[String])
?
Run Code Online (Sandbox Code Playgroud)
或者您可以在类的实例上进行模式匹配:
def myFunc2[T](t: T) = t match {
case _: TraitA => println("A")
case _: TraitB => println("B")
case _ => println("?")
}
scala> myFunc2(new ClassA)
A
scala> myFunc2(Some(5))
?
Run Code Online (Sandbox Code Playgroud)
您还可以通过类清单以语法上不那么突兀的方式使用第一种方法:
def myFunc3[T](implicit mf: ClassManifest[T]) = {
val clazz = mf.erasure
if (classOf[TraitA] isAssignableFrom clazz) println("A")
else if (classOf[TraitB] isAssignableFrom clazz) println("B")
else println("?")
}
scala> myFunc3[ClassA]
A
scala> myFunc3[String]
?
Run Code Online (Sandbox Code Playgroud)
如果if/else变得很糟糕,你也可以选择不同类型的调度:
object MyFunc {
val dispatch = Map(
classOf[TraitA] -> (() => println("A")),
classOf[TraitB] -> (() => println("B"))
)
val default = () => println("?")
def apply[T](implicit mf: ClassManifest[T]) =
dispatch.find(_._1 isAssignableFrom mf.erasure).map(_._2).getOrElse(default)()
}
scala> MyFunc[ClassA]
A
scala> MyFunc[String]
?
Run Code Online (Sandbox Code Playgroud)
请注意,您使用此代码的任何通用代码都需要具有可用的类清单(作为隐式参数或简写,[T: ClassManifest].