Как правильно заметил Мирко, вы не можете абстрагироваться от метода копирования. Я поддерживаю точку зрения Дэниела, что клонирование может быть тем, что вам нужно, хотя я бы обернул его некоторым вспомогательным кодом, чтобы уменьшить шаблон.
Вы можете определить черту mixin с функцией копирования и просто смешать ее с вашими классами дел:
trait ClonableAs[T] extends Cloneable { this: T =>
def makeClone() = super.clone().asInstanceOf[T]
}
case class Foo(i: Int) extends ClonableAs[Foo]
List(Foo(1), Foo(2), Foo(3)).map(_.makeClone())
Таким образом, вместо добавления идентичного метода к каждому из ваших классов дел, вы заставляете их расширять черту помощника, которая делает их чище и экономит некоторые нажатия клавиш.
С другой стороны, клонирование не имело бы смысла для неизменных объектов, поэтому я предполагаю, что у ваших классов изменчивое состояние. Я бы посоветовал вам пересмотреть, если вы действительно не можете сделать их неизменяемыми, и использовать этот тип клонирования только в крайнем случае. Неизменность защитит себя от класса ошибок.