【问题标题】:Calls to supertype methods in traits allowed with `extends` but not with self-types允许使用 `extends` 调用 trait 中的超类型方法,但不允许使用自身类型
【发布时间】:2014-03-14 19:21:48
【问题描述】:

考虑:

trait SuperBar { def superBarMethod = ??? }
trait Bar extends SuperBar

trait FooWithSelfType { this: Bar =>
  super.superBarMethod // error: value superBarMethod is not a member of AnyRef
}

trait FooWithExtends extends Bar {
  super.superBarMethod
}

这种限制是由于一些底层实现的缺陷,还是出于某种原因实际上是这样设计的?

我的看法是,如果已知thisBar 类型,并且已知BarSuperBar 的子类型,那么在this 上调用任何SuperBar 方法应该允许。

【问题讨论】:

  • 为什么需要使用super. 限定对superBarMethod 的调用。它已经可用,无需使用 super.,因为您已声明自己需要 Bar 可用。

标签: scala inheritance traits self-type


【解决方案1】:

FooWithSelfType 可能知道它是一个Bar,但它实际上并不是FooWithSelfType 继承层次结构的一部分,因此它无权访问super,除了super 明确是其继承层次结构的一部分。如果你有

trait Baz extends SuperBaz { this : Bar => 
  /* ... */
}

如果SuperBazSuperBar 都有可能,你怎么知道super 指的是什么?

【讨论】:

  • 那么关于trait Baz extends SuperBaz with Bar { super.superBarMethod } 就不能问同样的“你怎么知道...”的问题?这是一个完全合法的结构。 ...换句话说:如果superextends SuperBaz with Bar 的情况下工作,它也可以在extends SuperBaz { this: Bar => 的情况下工作,在我看来......不确定编译器会付出多少努力.
  • P.S.毫无疑问,对于为什么编译器目前拒绝接受这一点,有一个技术解释,但我想知道是否有一个更根本的原因,编译器不能(被要求)“按预期”处理这个问题。
  • @ErikAllik - 有线性化规则,您可以通过重新排序特征列表来获得所需的线性化。但是,您不能根据自类型注释对它们进行重新排序。更不用说线性化已经足够复杂了。
  • 好的,尽管我还不能完全理解它,但我相信你的能力。
  • @ErikAllik - 简而言之,class Qux extends Foo with Bar with BazBaz 作为其直接超类型。 class Qux extends Baz with Foo with Bar 具有 Bar 作为其直接超类型。无需担心自我类型如何交互,这已经足够繁琐了。
【解决方案2】:

Self-type 表示当前的 trait 最多应该是你用作 self-type 的类型。这意味着该给定类型的所有子类型都可以混合当前特征。考虑到这一点,super 仅指当前 trait 是其子类/trait 的类/trait。

我不得不说我不久前遇到了这个想法,我认为这可能是一个弱点,我的意思是我们可以想象编译器可以同时查找超类中的方法和 self 类型中的方法超类。

【讨论】:

  • 换句话说,我认为这是对super 定义方式的限制,而不是数学限制...?
  • 我也是这么想的。这只是我的拙见。
猜你喜欢
  • 1970-01-01
  • 2018-10-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-28
  • 2021-09-24
  • 2021-08-24
  • 2015-12-13
相关资源
最近更新 更多