【问题标题】:Is there a way to forbid overriding a member in a mixin?有没有办法禁止在 mixin 中覆盖成员?
【发布时间】:2016-06-28 11:06:05
【问题描述】:

所以,我定义了一堆可堆叠的特征,如下所示:

trait Base { 
  val prefix: String = ""
  def foo = ""
}

trait Foo extends Base { 
  override def foo = prefix + "/Foo" + ";" + super.foo
}

trait Bar extends Base {
  override def foo = prefix + "/Bar" + ";" + super.foo
}

class Bat extends Foo with Bar {
  override val prefix: String = "Bat"
}

new Bat().foo

上面返回Bat/Bar;Bat/Foo,这就是我想要的。 现在,问题当然是,prefix 只能有一个实例,而且,如果其中一个 mixin 试图覆盖它,它将无法工作,因为在 Bat 中定义的那个“胜过”它。这没关系,除了,我希望“行不通”的事情是明确的。

任何人都可以想到某种技巧,这会导致尝试在 trait 中覆盖 prefix 而不是在从它继承的类中导致编译错误?

【问题讨论】:

  • 您可以将prefix 标记为final,但您也无法在Bat 中覆盖它。
  • @EndeNeu 是的,我想很多:)

标签: scala mixins


【解决方案1】:

您可以将特征一分为二并利用explicitly typed self-references,如下所示:

trait Base {
  def foo = ""
}

trait Prefix {
  val prefix: String = ""
}

trait Foo extends Base { this: Prefix =>
  override def foo = prefix + "/Foo" + ";" + super.foo
}

trait Bar extends Base { this: Prefix =>
  override def foo = prefix + "/Bar" + ";" + super.foo
}

class Bat extends Prefix with Foo with Bar {
  override val prefix: String = "Bat"
}

new Bat().foo

【讨论】:

  • 我不明白这有什么帮助。没有什么能阻止我做trait Bar extends Base with Prefix,并在那里覆盖prefix,这正是我想要限制的。
  • 是的,当前的建议只有在您遵循特定的工作流程时才有效。提供更安全保证的一种方法是将Prefix 标记为sealed,并将FooBar 特征保留在另一个文件中。如果您认为它会更好地解决问题,我可以在这个方向上编辑我的答案。
  • 不是很难,但我不希望它被密封 :) 将Base 视为一些默认的 http 路由实现,提供通用功能,如授权等。Foo然后Bar 是到具体服务的路由(例如,用户配置文件、管理界面、存储等),可以由一台或多台服务器提供。 Bat 是网络服务器。它混合了FooBar(可能还有其他)来创建路由,并将prefix 定义为挂载点。现在,您可以看到,为什么我不希望 Prefix 被密封 - 有许多不同的服务器,我们不希望它们都在一个文件中。
【解决方案2】:

由于 trait 可以扩展类,所以没有办法禁止 trait 有一个覆盖的前缀定义,但允许类有一个。

顺便说一句,关于“不起作用”的部分,我不同意,它按预期工作。我很确定覆盖属性的开发人员完全意识到她很好......覆盖了她继承的内容。

那么类继承类呢?

如果您想禁止继承,唯一要做的就是在实际上不希望它被进一步覆盖的任何 Trait 或 Class 中标记 val/def final(在您的示例中,这将是 Foo 和酒吧)。

【讨论】:

  • 我愿意接受扩展类的特征作为一个例外。首先,因为它更像是一个奇怪的极端情况,不会经常发生,其次,因为这些特征无论如何都不会真正堆叠(你不能混合多个),所以它不是真的这里有很多因素。
  • 这只是表明该语言不允许您将继承限制为类。有可能(使用或不使用)的事实证明你不会实现你想要的。
  • 不确定某事是可能的事实如何证明某事 else 不是,但没关系。关于“开发者覆盖属性...”,这是一个哲学概念,但在实践中并没有太大帮助,尤其是在涉及堆叠和多重继承时。将String 分配给Int 的开发人员也应该意识到它可能导致的问题。你会用它作为反对严格类型和编译时类型安全的论据吗?继承类的类很好,因为它们不堆叠。
  • 我不想争论。我试图在我的回答中解释为什么你想要的东西不可行,如果你对这个答案不满意,请随意投反对票:)
  • 好吧,我没有问为什么它不可行 :) 尽管你有任何论点,但它确实可能使它可行,坦率地说,只是不' t 似乎在这里根本不适用。是的,特征可以扩展类,类可以扩展类......我看不出这与将特定成员限制为仅在(非抽象)类中定义的可能性有什么关系。
猜你喜欢
  • 2021-07-25
  • 2016-12-12
  • 2010-09-06
  • 2018-10-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-24
  • 2011-07-07
相关资源
最近更新 更多