如何确定 class 是父 class 的子 class 还是特征?
How to determine if a class is a subclass of a parent class or trait?
在 Scala 中,我们如何确定 class 是父 class 的子 class 还是特征?例如:
trait MyTrait
class MyParentClass()
class MyOtherParentClass()
case class MySubClass() extends MyParentClass with MyTrait
case class MyOtherSubClass() extends MyOtherParentClass
是否可以在不实例化对象和通过反射 API 的情况下识别 class(例如 MySubClass
是否从 MyParentClass
或 MyTrait
扩展?给定一个未知的泛型类型 T
,如果 T
扩展了一个特定的父 class 或特征:
,我有兴趣让它匹配一个案例
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
或 implicitbox.Priority
I updated the question with an example of the desired usage
看来你想要一个类型class
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()
类型 class 是模式匹配的 compile-time(即 type-level)替代。
如果隐式之间存在歧义,您可以确定它们的优先级。
Just curious, do you know if there is a way to do this in a simple one line conditional such as if (T extends from MyParentClass) then ...
through reflection APIs (is it possible through classOf[]
or 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 ???
}
但是隐式和类型是比(compile-time 或尤其是运行时)反射更可取的方式。根本不清楚为什么需要反射。
https://users.scala-lang.org/t/how-to-access-the-method/6281
在 Scala 中,我们如何确定 class 是父 class 的子 class 还是特征?例如:
trait MyTrait
class MyParentClass()
class MyOtherParentClass()
case class MySubClass() extends MyParentClass with MyTrait
case class MyOtherSubClass() extends MyOtherParentClass
是否可以在不实例化对象和通过反射 API 的情况下识别 class(例如 MySubClass
是否从 MyParentClass
或 MyTrait
扩展?给定一个未知的泛型类型 T
,如果 T
扩展了一个特定的父 class 或特征:
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
或 implicitbox.Priority
I updated the question with an example of the desired usage
看来你想要一个类型class
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()
类型 class 是模式匹配的 compile-time(即 type-level)替代。
如果隐式之间存在歧义,您可以确定它们的优先级。
Just curious, do you know if there is a way to do this in a simple one line conditional such as
if (T extends from MyParentClass) then ...
through reflection APIs (is it possible throughclassOf[]
ortypeOf[]
?)
您可以在运行时执行此操作
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 ???
}
但是隐式和类型是比(compile-time 或尤其是运行时)反射更可取的方式。根本不清楚为什么需要反射。
https://users.scala-lang.org/t/how-to-access-the-method/6281