Scala:抽象类构造函数参数与 Trait val 成员?

标签 scala abstract-class traits

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

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”概念。尽管如此,我是否有任何理由应该在某处使用抽象类?谢谢!

最佳答案

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

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

同样,特征初始化顺序取决于线性化(混合顺序),这就是特征成员应该是 def 而不是 val 的原因。 (并且您始终可以使用 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 错误以了解早期定义,因此这些定义的优先级较低。)

关于Scala:抽象类构造函数参数与 Trait val 成员?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13828926/

相关文章:

java - 多个功能是 logback 标记的良好用例吗?

c++ - 确保一个类不是抽象的

java - 使用实现接口(interface)的抽象类 (Java)

java - Scala 编译器如何处理具体的特征方法?

scala - IO Monad 中的 future 行为

scala - df.SaveAsTable和spark.sql(创建表..)之间的区别

c++ - 如何使用类型特征来定义部分抽象的模板基类?

Rust:对向量中结构的多态调用

php - PHP 中 Trait 和抽象类的区别

scala - 使用布隆过滤器减少