【问题标题】:Scala: abstract class constructor parameter vs Trait val members?Scala:抽象类构造函数参数与 Trait val 成员?
【发布时间】:2012-12-11 21:38:50
【问题描述】:

我注意到有几个关于如何在抽象类和特征之间进行选择的讨论,但似乎没有一个集中在以下点上。让我使用抽象类的一个原因是,它们可以有构造函数参数,而特征不能。但是为什么不如下

trait X {
  def haha: Int
}
class Y(val haha: Int) extends X

甚至没有必要提前定义以使一切正常运行(我担心)。抽象类版本是

abstract class X(haha: Int)
class Y(val haha: Int) extends X(haha)

而且我不喜欢抽象类的版本,因为当你多次扩展时,这些构造函数参数无处不在(也许有人告诉我如何避免这种情况?)。

我知道抽象类可以更好地使用 Java 进行插值,并且更符合“is-a”概念。尽管如此,有什么理由我应该在某处使用抽象类吗?谢谢!

【问题讨论】:

    标签: scala abstract-class traits


    【解决方案1】:

    类参数不必是成员(字段或定义)。

    abstract class X(haha: Int) {
      val hoho = 2 * haha  // compile-time constant
    }
    

    同样,特征初始化顺序取决于线性化(混合顺序),这就是特征成员应该是 defs 而不是 vals 的原因。 (而且你总是可以用 val 覆盖 def。)使用抽象类,你知道你的 super 是谁,并且你正在为子类定义扩展点。

    但请注意,您的抽象类的 val 位置错误:

    abstract class X(val haha: Int)
    class Y(haha: Int) extends X(haha)
    

    也就是说,您会期望 X 决定参数是否为 val (并且不一定是)。在 X 或 Y 中使用参数可以把它变成一个字段。

    您对类的值参数的观察也适用于类型参数:将 Foo[A] 向上传递是多么令人讨厌。所以在 Scala 中,我们可以有一个成员类型 A 来代替它可以保持抽象,直到在叶子中定义。但这实际上与定义特征还是类无关。

    但特征参数正在进入 Scala。 (请参阅 Scala 错误以了解由于这个原因而属于低优先级的早期定义。)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-04-15
      • 1970-01-01
      • 1970-01-01
      • 2016-03-12
      • 2022-01-22
      • 1970-01-01
      相关资源
      最近更新 更多