cod*_*ark 0 generics reflection scala scala-reflect
在 Scala 中,我们如何确定一个类是父类的子类还是特征?例如:
trait MyTrait
class MyParentClass()
class MyOtherParentClass()
case class MySubClass() extends MyParentClass with MyTrait
case class MyOtherSubClass() extends MyOtherParentClass
Run Code Online (Sandbox Code Playgroud)
是否可以通过反射 API来确定类是否MySubClass从实例化对象扩展MyParentClass或MyTrait不实例化?给定一个未知的泛型类型T,如果T扩展特定的父类或特征,我有兴趣让它匹配一个案例:
def example[T](): Unit = {
T match {
case if T extends MyParentClass => ...
case if T extends MyOtherParentClass => ...
case if T extends MyOtherTrait => ...
case _ => default case ...
}
Run Code Online (Sandbox Code Playgroud)
如果你写
case class MySubClass() extends MyParentClass with MyTrait
Run Code Online (Sandbox Code Playgroud)
那么很明显MySubClass延长MyParentClass,并MyTrait因此您可以检查的泛型类型T与
def test[T](implicit ev: T <:< MyParentClass, ev1: T <:< MyTrait) = ???
test[MySubClass] // compiles
Run Code Online (Sandbox Code Playgroud)
在编译时。
如果问题是你想用 OR 而不是 AND 来检查,那么你可以使用shapeless.OrElse或implicitbox.Priority
我用所需用法的示例更新了问题
看来你想要一个类型类
trait Example[T] {
def example(): Unit
}
object Example {
implicit def subtypeOfMyParentClass[T <: MyParentClass] = new Example[T] {
override def example(): Unit = ???
}
implicit def subtypeOfMyOtherParentClass[T <: MyOtherParentClass] = new Example[T] {
override def example(): Unit = ???
}
implicit def subtypeOfMyOtherTrait[T <: MyOtherTrait] = new Example[T] {
override def example(): Unit = ???
}
implicit def default[T] = new Example[T] {
override def example(): Unit = ???
}
}
def example[T]()(implicit e: Example[T]): Unit = e.example()
Run Code Online (Sandbox Code Playgroud)
类型类是模式匹配的编译时(即类型级)替换。
如果隐式之间存在歧义,您可以优先考虑它们。
只是好奇,您知道是否有一种方法可以通过简单的单行条件来执行此操作,例如
if (T extends from MyParentClass) then ...通过反射 API(是否可以通过classOf[]或typeOf[]?)
你可以在运行时做到这一点
import scala.reflect.runtime.universe._
def example[T: TypeTag](): Unit =
if (typeOf[T] <:< typeOf[MyParentClass]) ???
else if (typeOf[T] <:< typeOf[MyOtherParentClass]) ???
else if (typeOf[T] <:< typeOf[MyOtherTrait]) ???
else ???
Run Code Online (Sandbox Code Playgroud)
或者
import scala.reflect.ClassTag
def example[T: ClassTag](): Unit =
if (classOf[MyParentClass] isAssignableFrom classOf[T]) ???
else if (classOf[MyOtherParentClass] isAssignableFrom classOf[T]) ???
else if (classOf[MyOtherTrait] isAssignableFrom classOf[T]) ???
else ???
Run Code Online (Sandbox Code Playgroud)
或在编译时
import scala.language.experimental.macros
import scala.reflect.macros.blackbox
def example[T](): Unit = macro exampleImpl[T]
def exampleImpl[T: c.WeakTypeTag](c: blackbox.Context)(): c.Tree = {
import c.universe._
if (weakTypeOf[T] <:< typeOf[MyParentClass]) ???
else if (weakTypeOf[T] <:< typeOf[MyOtherParentClass]) ???
else if (weakTypeOf[T] <:< typeOf[MyOtherTrait]) ???
else ???
}
Run Code Online (Sandbox Code Playgroud)
但是隐式和类型是一种更可取的方式,而不是(编译时或特别是运行时)反射。目前还不清楚为什么你需要反思。
https://users.scala-lang.org/t/how-to-access-the-method/6281
| 归档时间: |
|
| 查看次数: |
175 次 |
| 最近记录: |