假设我有以下类型
class Foo
trait Bar
Run Code Online (Sandbox Code Playgroud)
有没有办法制作一个接受Type参数T的方法,并确定该T是否为Bar?例如,
def isBar[T <: Foo: Manifest] =
classOf[Bar].isAssignableFrom(manifest[T].erasure)
Run Code Online (Sandbox Code Playgroud)
可悲的是,isBar[Foo with Bar]
是false
因为擦除似乎抹去混入.
而且,manifest[Foo with Bar] <:< manifest[Bar]
是假的
这有可能吗?
我看了这个问题:如何判断Scala的具体类型是否扩展了某个父类?
但是这个答案不适用于混合特征,因为它们似乎被清除,如上所述.
kir*_*uku 22
这可以通过TypeTag(至少2.10M7)来实现:
scala> class Foo; trait Bar
defined class Foo
defined trait Bar
scala> import reflect.runtime.universe._
import reflect.runtime.universe._
scala> def isBar[A <: Foo : TypeTag] = typeOf[A].baseClasses.contains(typeOf[Bar].typeSymbol)
isBar: [A <: Foo](implicit evidence$1: reflect.runtime.universe.TypeTag[A])Boolean
scala> isBar[Foo]
res43: Boolean = false
scala> isBar[Foo with Bar]
res44: Boolean = true
Run Code Online (Sandbox Code Playgroud)
TypeTags提供Scala类型的1:1转换,因为它们代表编译器知道的类型.因此它们比普通的旧Manifest强大得多:
scala> val fooBar = typeTag[Foo with Bar]
fooBar: reflect.runtime.universe.TypeTag[Foo with Bar] = TypeTag[Foo with Bar]
Run Code Online (Sandbox Code Playgroud)
通过该方法,tpe
我们可以完全访问Scalas的新反射:
scala> val tpe = fooBar.tpe // equivalent to typeOf[Foo with Bar]
tpe: reflect.runtime.universe.Type = Foo with Bar
scala> val tpe.<tab><tab> // lot of nice methods here
=:= asInstanceOf asSeenFrom baseClasses baseType contains declaration
declarations erasure exists find foreach isInstanceOf kind
map member members narrow normalize substituteSymbols substituteTypes
takesTypeArgs termSymbol toString typeConstructor typeSymbol widen
Run Code Online (Sandbox Code Playgroud)
有可能在2.10之前做到这一点,而不是(据我所知)有清单:
def isBar[T <: Foo](implicit ev: T <:< Bar = null) = ev != null
Run Code Online (Sandbox Code Playgroud)
这有点像黑客,但它可以按照需要运行.
scala> isBar[Foo with Bar]
res0: Boolean = true
scala> isBar[Foo]
res1: Boolean = false
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
4595 次 |
最近记录: |