Наследование и повторное использование кода в составных чертах

В этом упрощенном эксперименте я хочу иметь возможность быстро создать класс с наращиваемыми характеристиками, который может сообщать о том, какие характеристики использовались для его построения. Это сильно напоминает мне образец декоратора, но яЯ предпочел бы реализовать это во время компиляции, а не во время выполнения.

Рабочий пример с избыточным кодом

class TraitTest {
  def report(d: Int) : Unit = {
    println(s"At depth $d, we've reached the end of our recursion")
  }
}

trait Moo  extends TraitTest {
  private def sound = "Moo"
  override def report(d: Int) : Unit = {
    println(s"At depth $d, I make the sound '$sound'")
    super.report(d+1)
  }
}
trait Quack extends TraitTest {
  private def sound = "Quack"
  override def report(d: Int) : Unit = {
    println(s"At depth $d, I make the sound '$sound'")
    super.report(d+1)
  }
}

проведение(new TraitTest with Moo with Quack).report(0) затем сообщит:

> At depth 0, I make the sound 'Quack'
  At depth 1, I make the sound 'Moo'
  At depth 2, we've reached the end of our recursion 

К сожалениюТам много избыточного кода, который заставляет мой глаз дергаться. Моя попытка убрать это приводит меня к:

Нерабочий пример без избыточного кода

class TraitTest {
  def report(d: Int) : Unit = {
    println(s"At depth $d, we've reached the end of our recursion")
  }
}

abstract trait Reporter extends TraitTest {
  def sound : String
  override def report(d: Int) : Unit = {
    println(s"At depth $d, I make the sound '${sound}'")
    super.report(d+1)
  }
}

trait Moo extends Reporter {
  override def sound = "Moo"
}
trait Quack extends Reporter{
  override def sound = "Quack"
}

Когда мы снова выполняем(new TraitTest with Moo with Quack).report(0)Теперь мы видим:

> At depth 0, I make the sound 'Quack'
  At depth 1, we've reached the end of our recursion

Вопрос 1: Где линия дляMoo» идти? Я

Я предполагаю, что Скала видит толькоoverride def report(d: Int) один раз, и, следовательно, только помещает его в цепочку наследования один раз. Я'Я хватаюсь за соломинку, но если этоВ таком случае, как я могу обойти это?

Вопрос 2: Как каждая конкретная черта может обеспечить уникальность?sound

Решив первый вопрос, я бы предположил результаты выполнения(new TraitTest with Moo with Quack).report(0) будет выглядеть примерно так, в связи с тем, как наследованиеsound должно сработать.

> At depth 0, I make the sound 'Quack'
  At depth 1, I make the sound 'Quack'
  At depth 2, we've reached the end of our recursion  

Как мы можем сделать так, чтобы каждая черта использовалаsound указано в немс реализацией?

Ответы на вопрос(3)

Ваш ответ на вопрос