首页 文章

抽象类型自我类型覆盖,并且错误“值xxx不是Component.this.T的成员”

提问于
浏览
2

错误如下所示:

trait Base { type T }

trait Component { self: Base =>
  override type T <: MyT

  val factory: Factory 

  trait Factory { def get_t: T }

  trait MyT { def xxx: Unit }

  class User {
    val t: T = factory.get_t

    def yyy = t.xxx
  }
}

trait ComponentImpl { self: Component => 
  type T = TImpl

  class TImpl extends MyT {
    def xxx = println("xxx")
  }

  val factory = new Factory {
    def get_t: T = new TImpl
  }
}

我收到错误:

<console>:26: error: value xxx is not a member of Component.this.T
       def yyy = t.xxx

有了一些冗余,我还发布了@slouc和@Kolmar建议的最小例子

trait Base { type T }

trait MyT { def xxx: Unit }

trait Component { self: Base =>
  override type T <: MyT
  val t: T
  def yyy = t.xxx // error
}

似乎我无法利用约束给出的增量,部分知识 .

My question is not about the approach ,而不是我有兴趣了解错误背后的原因 .

为了提供更多的上下文,我还要补充一点,当我尝试将继承关系转换为两个组件之间基于自我类型的关系时,我遇到了这个问题 .

2 回答

  • 1

    使用自我类型注释,您基本上告诉编译器自引用具有不同的类型

    self: Base
    

    如果你用任何正常的表达式来做这个,那么现在唯一的类型就是Base . 不知何故,类型注释作为特殊情况处理并保持其原始类型,我们实际看起来的类型是

    self: Base with Component
    

    现在,不知怎的,如果你引用Component.this它似乎在被覆盖的类型成员的情况下松散这些信息(或者可能覆盖只是错误的方式,但我看不出任何解释这不是一个bug)

    现在,如果您实际注释此类型,问题就会消失:

    trait Component { self: Base with Component => ... }
    

    这也清楚地表明这是一个错误,因为这很好:

    trait Component { self: Base =>
      val v:  Base with Component = self
    }
    

    这实际上是一个已知的Bug:

    https://issues.scala-lang.org/browse/SI-7255?jql=text%20~%20%22override%20self%20type%20abstract%22

  • 2

    有趣的问题 . 这是一个简化的例子:

    trait Base { type T }
    
    trait MyT { def xxx: Unit }
    
    trait Component { self: Base =>
      override type T <: MyT
      val t: T
      def yyy = t.xxx // error
    }
    

    请注意三件事:

    1.将自我类型注释更改为继承使一切工作成功:

    trait Component extends Base {
      override type T <: MyT
      val t: T
      def yyy = t.xxx
    }
    

    2.自我类型的超越方法没有问题:

    trait Base { def foo }
    
    trait Component { self: Base =>
      override def foo = println("foo")
    }
    

    3.如果不是缩小类型T而是使其具体化,那么最重要的是:

    trait Base { type T }
    
    trait Component { self: Base =>
      override type T = List[Int]
      val t: T
      def yyy = t.reverse
    }
    

    所以,我对这个问题的表述是 - 为什么在继承的情况下,所有三种情况都可以正常工作(1.覆盖方法,2 . 通过缩小覆盖抽象类型成员,3 . 通过使抽象类型成员具体化来覆盖抽象类型成员),但在自我类型的情况下,第二种情况是有问题的,而其他两种情况工作正常?

    考虑编辑您的问题(删除 ComponentImplFactory 等)以简化其他读者的问题 .

相关问题