Для `case-класса Cc(a: Int, b: Int) расширяется MyTraitA`, где`MyTraitA` появляется с признаками `Product` и`Serializable`?

Из-за линеаризации наследования в Scala я хотел бы понять, как черты, которые я указываю для класса наблюдения, упорядочиваются относительно двух черт, автоматически генерируемых и добавляемых компилятором Scala; т.е. Product with Serializable (и, к сожалению, это не ProductN[...] по состоянию на 2.12).

Я довольно тщательно искал и не нашел прямого обращения. Учитывая следующее:

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, есть ли нежелательные взаимодействия, потому что оба Product а также Product2 появляются вместе?

1 ответ

Благодаря глубокому прочтению ссылки, предоставленной в комментарии Богдана Вакуленко, явный ответ на первый вопрос - пункт 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
}
Другие вопросы по тегам