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

Из-за линеаризации наследования в 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 Ответ

3 голосов
/ 28 мая 2019

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