首页 > 解决方案 > 检查类型子类型时结果不一致

问题描述

有时,当我检查一个类是否扩展了一个特征时,我会得到不一致的结果。我正在使用 scala 2.12.8。

我的项目用于ru.Type动态构建操作链。一个操作的输出必须符合下一个操作的输入。

在链接两个操作之前,我使用以下方法检查类型是否兼容:

def checkFrom(t: ru.Type): Boolean = t <:< ru.typeOf[ExpectedTrait[_, _, _]]

但有时(实际上很少)<:<返回 false 而不是 true(我没有确定原因)。我添加了调试消息:

def checkFrom(t: ru.Type): Boolean = {
  val expectedType = ru.typeOf[ExpectedTrait[_, _, _]]
  val r = t <:< expectedType
  if (!r) println(s"$t is not a $expectedType (${t <:< expectedType})")
  r
}

我可以看到如下消息:MyClass is not a ExpectedTrait (true)。第一次评估<:<返回 false ,第二次返回 true !

t 是一个Types$ClassNoArtgsTypeRef并且 expectedType 是一个Types$ExistentialType

--edit-1--

所有 ru.Type 都来自ru.typeOf[X]. 在这种情况下,我不使用rm.classSymbol(x.getClass).toType.

这个问题可能与inconsistency-with-scala-reflection-library有关

它是否存在解决方法?

--编辑-2--

我可以使用以下代码重现错误:

import scala.reflect.runtime.{universe => ru}

abstract class BaseClass[A, This <: BaseClass[A, This]](a: A) {
  def newInstance(a: A): This
}

abstract class ExtClass[A, This <: ExtClass[A, This]](a: A) extends BaseClass[A, This](a)

class MyClass(n: Int) extends ExtClass[Int, MyClass](n) {
  override def newInstance(a: Int): MyClass = new MyClass(a)
}

object ReflectionTest extends App {
  def test[T: ru.TypeTag](tpe: ru.Type): Boolean = {
    val r = tpe <:< ru.typeOf[T]
    if (!r) println(s"test fails: ${tpe <:< ru.typeOf[T]}")
    r
  }
  println((0 until 1000).par.forall(_ => test[BaseClass[_, _]](ru.typeOf[MyClass])))
}

我认为关键是并行执行。这是一个输出示例:

test fails: true
test fails: true
false

标签: scalascala-reflect

解决方案


推荐阅读