对于"案例类 Cc(a: Int, b: Int) 扩展 MyTraitA","MyTra



由于 Scala中的继承线性化,我想了解我为案例类指定的特征是如何相对于 Scala 编译器自动生成和添加的两个特征进行排序的;即Product with Serializable(令人失望的是,它不是从 2.12 开始ProductN[...])。

我已经非常彻底地搜索了,但我没有找到直接解决的问题。鉴于以下情况:

case class Cc(a: Int, b: Int) extends MyTraitA with MyTraitB

在 Scala 编译器自动生成代码之后,以下哪项是关于结果继承排序的正确假设?

  1. case class Cc(a: Int, b: Int) extends MyTraitA with MyTraitB with Product with Serializable
  2. case class Cc(a: Int, b: Int) extends Product with Serializable with MyTraitA with MyTraitB

然后,我还有一个问题。如果我显式地将Product2[...]扩展到案例类,可能会产生哪些不良或意外的影响?以下是上面两段重复插入Product2[...]的代码:

  1. case class Cc(a: Int, b: Int) extends MyTraitA with MyTraitB with Product2[Int, Int] with Product with Serializable
  2. case class Cc(a: Int, b: Int) extends Product with Serializable with MyTraitA with MyTraitB with Product2[Int, Int]

IOW,是否存在任何不良的相互作用,因为ProductProduct2一起出现?

由于深入阅读了Bogdan Vakulenko评论中提供的链接,第一个问题的明确答案是第2项:

case class Cc(a: Int, b: Int) extends Product with Serializable with MyTraitA with MyTraitB

再次感谢波格丹·瓦库连科,第二个问题的答案是,在添加Product2[Int, Int]性状时,鉴于它扩展了Product性状,因此不应发生任何不良情况。


有一个非常有趣的奖励答案。如果需要将编译器生成的接口推送到特征继承排序的后面,则需要显式定义编译器生成的接口。有几种方法可以做到这一点。

第一个也是最简单的是更改如下所示的原始代码(没有引用Product也没有Serializable,并让编译器自动生成它们):

case class Cc(a: Int, b: Int) extends MyTraitA with MyTraitB

如下所示(明确定义Product并在特征列表的末尾Serializable):

case class Cc(a: Int, b: Int) extends MyTraitA with MyTraitB with Product with Serializable

第二种选择是将Product with Serializable添加到MyTraitA和/或MyTraitB中:

trait MyTraitA extends Product with Serializable
trait MyTraitB extends Product with Serializable
case class Cc(a: Int, b: Int) extends MyTraitA with MyTraitB

这种技术还导致理想的特征排序。

case class Cc(a: Int, b: Int) extends MyTraitA with MyTraitB with Product with Serializable

最后,集成Product2[Int, Int]就像显式定义所有内容一样简单,知道任何重叠都将通过 Scala 编译器中默认提供的出色多重继承解析策略自动解决:

case class Cc(a: Int, b: Int) extends MyTraitA with MyTraitB with Product2[Int, Int] with Product with Serializable {
override def _1: Int = a
override def _2: Int = b
}

相关内容

  • 没有找到相关文章

最新更新