自我类型注释阻碍了内部类的实例化。为什么?

时间:2011-11-21 15:46:04

标签: class scala abstract traits self-type

鉴于Outer类及其Inner类的抽象定义,我想实例化Inner1特征中定义的具体Outer1类。

abstract class Outer {
  type Inner_Tp <: Inner;
  abstract class Inner {
    self: Inner_Tp =>
  }
}

trait Outer1 {
  self: Outer =>
  protected class Inner1 extends Inner {
    self: Inner_Tp =>
  }
  def Inner1() = new Inner1()
}

Scala编译器过早地终止编译,给出了以下错误消息:“错误:类Inner1无法实例化,因为它不符合其自身类型Outer1.this.Inner1 with Outer1.this.Inner_Tp”。的为什么吗

在抽象上下文中定义所有Inner1类之后,它是Outer1特征。我想推迟type Inner_Tp的定义,直到特质混入一些具体的类。

2 个答案:

答案 0 :(得分:7)

对于Inner1,自我类型表示它将始终与抽象类型Inner_Tp一起实例化。这是在实例化时未实现的承诺:类型仅为Inner1而不是Inner1 with Inner_Tp

如果您需要延迟Inner_Tp的定义,还需要延迟创建任何将其作为自我类型的实例。这是绝对必要的,因为您无法生成您还不知道的类型的值。所以最好把方法抽象化。您也可以优化抽象类型:

trait Outer1 extends Outer {
   type Inner_Tp <: Inner1
   protected class Inner1 extends Inner

   def Inner1(): Inner_Tp
}

我不确定你的目标是什么,但你可能根本不需要自我类型(为了简洁,我把它们留了出来)。

答案 1 :(得分:1)

因为self: Inner_Tp表示不允许实例化Inner的子类型,除非它也是Inner_Tp的子类型。

self => Inner_Tp中重写Inner1只是重述约束,它不满足它。要获得类似的想法,当你有一个抽象类的后代时,如果它没有实现抽象方法,你必须再次写它是抽象的。你不能实现。与此相同,您重申了Inner_Tp是必需的,您没有Inner_Tp可用。

只要Inner_Tp是抽象类型,您将无法将其混合,因此您将无法编写new Inner1。您应该引入一个创建Inners的抽象方法。