简体   繁体   English

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

[英]Abstract types + self types + type overriding, and error “Value xxx is not a member of Component.this.T”

The error is illustrated in the following: 该错误说明如下:

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
  }
}

And I get the error: 我得到错误:

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

With some redundancy, I also post the minimal example as suggested by @slouc and @Kolmar 带着一些冗余,我还发布了@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
} 

It seems that I cannot leverage on the incremental, partial knowledge given by the constraint. 看来我无法利用约束所提供的增量的部分知识。

My question is not about the approach , rather I am interested in understanding the reasons behind the error. 我的问题不是方法 ,而是我有兴趣了解错误背后的原因。

To provide more context, I would also add that I got into this problem when trying to convert an inheritance relationship into a self-type-based relationship between two components. 为了提供更多的上下文,我还要补充一点,当试图将继承关系转换为两个组件之间基于自类型的关系时,我遇到了这个问题。

With the self type annotation you are basically telling the compiler that the self-reference has a different type 使用自我类型注释,您基本上是在告诉编译器自我引用具有不同的类型

self: Base

If you would do this with any normal expression, the only type self has now, is Base. 如果要使用任何正则表达式执行此操作,那么self唯一的类型就是Base。 Somehow type annotations are handled as a special case and maintain their original type as well, the type we actually seem to get is 以某种方式将类型注释作为特殊情况处理并保持其原始类型,我们实际上似乎得到的类型是

self: Base with Component

Now, somehow if you refer to Component.this it seems to loose this information in case of overwritten type members (or maybe the overwriting is just the wrong way around, but I cannot see any explanation that this is not a bug) 现在,以某种方式引用Component.this似乎会在类型成员被覆盖的情况下丢失此信息(或者覆盖是错误的方法,但是我看不到任何说明这不是错误)

Now if you actually annotate this type the problem goes away: 现在,如果您真正注释了这种类型,问题就消失了:

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

Which also clearly shows this is a bug because this works fine: 这也清楚地表明这是一个错误,因为它可以正常工作:

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

This is actually a known Bug: 这实际上是一个已知的错误:

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

Interesting question. 有趣的问题。 Here's a simplified example: 这是一个简化的示例:

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
}

Note three things here: 请注意此处的三件事:

1.Changing self type annotation to inheritance makes everything work out: 1.将自类型注释更改为继承可以使所有工作顺利进行:

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

2.Overriding methods from self-type is not problematic: 2.从自我类型覆盖方法没有问题:

trait Base { def foo }

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

3.If instead of narrowing type T we make it concrete, then the overriding works: 3.如果不是将T类型缩小,而是将其具体化,则覆盖的工作原理是:

trait Base { type T }

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

So, my formulation of the question would be - how come that in case of inheritance all three cases work just fine (1. overriding method, 2. overriding abstract type member by narrowing, 3. overriding abstract type member by making it concrete), but in case of self types second case is problematic, while other two work fine? 因此,我对这个问题的表述是-在继承的情况下,这三种情况如何都能正常工作(1.覆盖方法,2。通过缩小覆盖抽象类型成员,3。通过使其具体化覆盖抽象类型成员),但是在自我类型的情况下,第二种情况是有问题的,而其他两种情况很好吗?

Consider editing your question (removing ComponentImpl , Factory etc.) to simplify it for other readers. 考虑编辑您的问题(删除ComponentImplFactory等),以简化其他读者的阅读。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM