scala - 如何确定一个类是否是父类或特征的子类?
问题描述
在 Scala 中,我们如何确定一个类是父类的子类还是 trait?例如:
trait MyTrait
class MyParentClass()
class MyOtherParentClass()
case class MySubClass() extends MyParentClass with MyTrait
case class MyOtherSubClass() extends MyOtherParentClass
是否可以通过反射 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 ...
}
解决方案
如果你写
case class MySubClass() extends MyParentClass with MyTrait
然后显然MySubClass
扩展MyParentClass
,因此您可以使用MyTrait
以下方法检查泛型类型T
def test[T](implicit ev: T <:< MyParentClass, ev1: T <:< MyTrait) = ???
test[MySubClass] // compiles
在编译时。
如果问题是你想用 OR 而不是 AND 来检查,那么你可以使用shapeless.OrElse
orimplicitbox.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()
类型类是模式匹配的编译时(即类型级别)替换。
如果隐含之间存在歧义,您可以优先考虑它们。
只是好奇,您是否知道是否有一种方法可以通过简单的单行条件来执行此操作,例如
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 ???
或者
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 ???
或在编译时
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 ???
}
但是隐式和类型是一种更可取的方式,而不是(编译时或特别是运行时)反射。目前还不清楚为什么你需要反思。
https://users.scala-lang.org/t/how-to-access-the-method/6281
推荐阅读
- flutter - 无法显示来自快照的字符串
- javascript - JSDOC 记录事件监听器 (addEventListener)
- sql-server - 如何记录每个查询的自定义元数据/上下文信息
- python-3.x - 在python中将所有列中的所有负值替换为零
- java - Tomcat 中的 HTTP v/s AJP 连接器(就性能而言) - Tomcat 版本 9.x
- php - 如何在 CakePhp 中为用户捕获缓存
- google-chrome-devtools - Google Chrome 的 DevTools。在“网络”选项卡中隐藏所有状态为 200 的 HTTP 请求
- json - 如何说服 VS 代码接受 # 作为 JSON 文件中的注释?
- excel - 在特定字符和该字符之后删除部分
- sql - 如何更新 json 对象的键?