我可以在 Scala 中对类型参数执行匹配以查看它是否实现了特征吗?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5485817/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Can I perform matching on a type parameter in Scala to see if it implements a trait?
提问by codefly
I would like to have a method which returns a class of a certain type, but I want the method to behave differently depending on whether or not the class extends a particular trait as follows:
我想要一个返回特定类型类的方法,但我希望该方法的行为取决于该类是否扩展了特定特征,如下所示:
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
}
}
Is this possible, or am I going about it the wrong way?
这是可能的,还是我以错误的方式处理它?
Thanks
谢谢
采纳答案by Rex Kerr
You can't compare types directly, because there isn't anything there to compare (at runtime, due to erasure). You could work on a representation of your class:
你不能直接比较类型,因为没有任何东西可以比较(在运行时,由于擦除)。你可以处理你的类的表示:
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])
?
or you can pattern match on instances of the class:
或者您可以对类的实例进行模式匹配:
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))
?
You can also use the first approach in a syntactically less obtrusive way via class manifests:
您还可以通过类清单以语法上不那么突兀的方式使用第一种方法:
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]
?
and you can choose different sorts of dispatch also if the if/else becomes wieldy:
如果 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]
?
Note that any generic code that you use this from will need to have a class manifest available (either as an implicit parameter or in shorthand, [T: ClassManifest].
请注意,您从中使用它的任何通用代码都需要有一个可用的类清单(作为隐式参数或简写,[T: ClassManifest].
回答by Paolo Falabella
You need an instance to check the type. A generic by itself is just a placeholder for a type. You could do something like this:
您需要一个实例来检查类型。泛型本身只是一个类型的占位符。你可以这样做:
trait bTrait //common base trait
trait TraitA extends bTrait
trait TraitB extends bTrait
class ClassA extends TraitA
class ClassB extends TraitB
def myFunc[T <: bTrait](t:T) : String = //passing explicitly an instance of type T
{
t match {
case _ : TraitA => "TraitA"
case _ : TraitB => "TraitB"
}
}
println(myFunc(new ClassA)) //prints TraitA
回答by The Archetypal Paul
"want the method to behave differently depending on whether or not the class extends a particular trait"
“希望该方法的行为取决于该类是否扩展了特定特征”
This is almost a canonical description of inheritance. Can't you have a method in each trait that encapsulates the differing behaviour you're after?
这几乎是对继承的规范描述。你不能在每个特征中都有一个方法来封装你所追求的不同行为吗?

