【问题标题】:Why don't Scala traits allow constructor parameters?为什么 Scala 特征不允许构造函数参数?
【发布时间】:2015-06-06 05:11:24
【问题描述】:

我是 Scala 的新手,来自 Java,我只是在阅读有关特性的文章。经常提到的一件事是特征没有(不能?不会?)具有构造函数参数。我很想知道这是否有原因。

来自很久以前的数学/计算机科学背景,我想知道这是否是由于某些语言设计决定而不可避免的结果,还是有意识地决定避免某些继承/混合问题或其他问题?

希望有人知道,因为感觉事实背后可能有一些有趣的东西。

【问题讨论】:

  • 考虑到您几乎可以通过重写 val 并懒惰地执行构造函数主体的其余部分来模拟构造函数参数,我怀疑其背后有深层原因。当然,也许有。也许与 Java/Scala 互操作有关?
  • 特征没有构造函数。这几乎就是类和特征之间的决定性区别

标签: scala


【解决方案1】:

其他答案描述了语言;我怀疑你的问题可能真的是“为什么这样设计”。

我相信它源于扩展多个特征时会出现的尴尬和冗长,尤其是使用覆盖和类型,以及各种混合策略。

蛋糕模式通常会导致各种特征在混合类中以一种完全不可见的方式相互提供缺失的位 - 设计使然。并且混合可以是双向的,使用self-types。因此,从特征构造一个类对于编译器来说可能是一件非常麻烦的事情。 Scala 经常以简单的编译器设计和实现来换取语言使用和代码减少的简单性,这当然是一个很好的例子。

因此,虽然在简单的分层情况下,使用构造函数可能有用且足够,但对于更困难的非分层场景,它几乎肯定必须是其他机制的冗余。

【讨论】:

  • 我不同意这个结论,但给了 +1 是因为您试图按照(可能?)预期的方式回答问题。
  • @Madoc - 这是一个弱的答案 - 我对所有的赞成票感到尴尬。希望像丹尼尔这样的人能提供具体的意见。
  • 你对我的问题背后的意图是正确的:)所以谢谢你。
【解决方案2】:

Scala 3 将允许特征参数。这是来自docs 的示例

trait Greeting(val name: String) {
  def msg = s"How are you, $name"
}

class C extends Greeting("Bob") {
  println(msg)
}

【讨论】:

    【解决方案3】:

    答案是:这就是现在的 Scala。

    但未来可能不是这样:特征参数可以取代早期的初始化器。 (参见 Martin Odersky 最近的 Scala Days 演示文稿第 34 页) Scala: Where It Came From & Where It is Going

    【讨论】:

      【解决方案4】:

      特征没有构造函数参数,因为特征不能被构造。给定任何 trait T 不可能精确地实例化任何类型的对象 T。你可以用 vals 覆盖 trait defs,所以

      trait Foo {
        def bar: String
      }
      class Baz(override val bar: String) extends Foo
      

      您不能直接构造它们,因为 new MyTrait {} 实际上是 new Object with MyTrait {} 匿名类的糖

      【讨论】:

      • 嗯。同样的逻辑也适用于抽象类,不是吗?我会说特征应该允许有构造函数,我也不明白为什么不允许它们。
      【解决方案5】:

      Trait 是 Java 接口的模拟。主要区别在于 trait 可以为其方法提供默认实现。

      所以 Java 接口不能有构造函数,Scala 特征也是如此

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-03-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多