错误如下所示:
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 回答
使用自我类型注释,您基本上告诉编译器自引用具有不同的类型
如果你用任何正常的表达式来做这个,那么现在唯一的类型就是Base . 不知何故,类型注释作为特殊情况处理并保持其原始类型,我们实际看起来的类型是
现在,不知怎的,如果你引用Component.this它似乎在被覆盖的类型成员的情况下松散这些信息(或者可能覆盖只是错误的方式,但我看不出任何解释这不是一个bug)
现在,如果您实际注释此类型,问题就会消失:
这也清楚地表明这是一个错误,因为这很好:
这实际上是一个已知的Bug:
https://issues.scala-lang.org/browse/SI-7255?jql=text%20~%20%22override%20self%20type%20abstract%22
有趣的问题 . 这是一个简化的例子:
请注意三件事:
1.将自我类型注释更改为继承使一切工作成功:
2.自我类型的超越方法没有问题:
3.如果不是缩小类型T而是使其具体化,那么最重要的是:
所以,我对这个问题的表述是 - 为什么在继承的情况下,所有三种情况都可以正常工作(1.覆盖方法,2 . 通过缩小覆盖抽象类型成员,3 . 通过使抽象类型成员具体化来覆盖抽象类型成员),但在自我类型的情况下,第二种情况是有问题的,而其他两种情况工作正常?
考虑编辑您的问题(删除
ComponentImpl
,Factory
等)以简化其他读者的问题 .