0

考虑以下示例:

sealed trait Granularity
object Granularity {

  case object Full extends Granularity

  sealed trait Partial extends Granularity {
    type GranularityKey
  }

  case object StringGranularity extends Partial {
    override type GranularityKey = String
  }
}

sealed trait Test{
  type T <: Granularity
}
object Test {

  type Aux[TT <: Granularity] = Test{ type T = TT }

  case object Cmp extends Test{
    override type T = StringGranularity.type
  }

  case object Fll extends Test{
    override type T = Full.type
  }
}
     
case class Tst[Gran <: Partial, T <: Test.Aux[Gran]](t: T#T#GranularityKey)
                                                          ^
                                                          |___Advanced language feature: reflective call

在类型选择中出现了关于一些反射调用的想法信号T#T#GranularityKey

你能解释一下这里会发生什么反射调用吗?那么它实际上是类型安全的吗?

4

1 回答 1

1

也许,因为下一个type Aux[TT <: Granularity] = Test{ type T = TT }- 基本上你说这里有一些Test应该在T其中定义类型别名。我认为这里的编译器逻辑类似于Scala 实现中的Duck Typing。例如,您可以定义type Foo{ def bar(): Unit}并尝试下一步

class FooImpl {
  def bar(): Unit = println("Bar")
}
val foo: Foo = new FooImpl
foo.bar()

如您所见FooImpl,它不会继承任何内容,但仍然可以为 type 赋值Foo,因为它满足拥有 method 的条件bar,但由于 JVM 限制或字节码限制 -foo.bar()调用将是反射的,这意味着通过 Java Reflection API。但是,这种方法是完全类型安全的。

也许,Idea 也因此认为traitT内部的类型别名Test会通过 Reflection API 被调用。

于 2021-01-26T07:59:51.513 回答