【问题标题】:Using Inner Classes As Type Arguments使用内部类作为类型参数
【发布时间】:2013-10-12 19:20:34
【问题描述】:

我需要使用内部类或抽象类型作为外部类型的类型参数,例如在下面高度简化的示例中:

trait A[T <: Ordered[T]] {
}

class B extends A[C] { //<-- Compiler error, type C not found.
  class C extends Ordered[C] {
  }
}

我在我的库中遇到了一个相当棘手的设计问题,我没有看到任何令人满意的方法来避免这种构造。我尝试了许多不同的方法来从类型参数中引用内部类,但都无济于事。

我的问题是:

  1. 有没有办法从外部类的类型参数中引用内部类?

  2. 如果不是,是否存在逻辑上的不一致性,或者仅仅是编译器和语言规范的限制?

【问题讨论】:

    标签: scala generics inner-classes abstract-type


    【解决方案1】:

    首先,您需要将C 限定为内部类,例如使用投影:

    class B extends A[B#C] {
      class C extends Ordered[C]
    }
    

    这会产生“非法循环引用”,因此是编译器的限制

    您可以将A 中的类型构造函数参数更改为类型成员:

    trait A {
      type T <: Ordered[T]
    }
    
    class B extends A {
      class T extends Ordered[T] {
        def compare(that: T): Int = ???
      }
    }
    

    【讨论】:

    • 实际上,即使您的第一个示例编译成功,它也不是我所需要的。我需要 this.C,而不是 A#C,因为 C 实现了 Ordered[this.C] 而不是 Ordered[B#C]。似乎能够使用内部类和抽象类型作为类型参数会很有用(事实上,使用类型参数作为参数很常见)。同样,我不确定允许这样做是否会在类型系统中产生一些逻辑不一致,或者它只是语言的词汇限制。
    • 这是正确的。可以通过引入trait BLike { class T ... }; class B extends BLike with A[BLike#T]来验证,它不会编译。未来版本的 Scala(“Dotty”)可能会融合类型构造函数参数和类型成员的概念。
    • 我认为这将是一个有趣的融合。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多