Я хотел бы знать, возможно ли абстрагировать метод копии классов случая. В основном у меня есть что-то как sealed trait Op
и затем что-то как case class Push(value: Int) extends Op
и case class Pop() extends Op
.
Первая проблема: класс случая без аргументов/участников не определяет метод копии. Можно попробовать это в REPL.
scala> case class Foo()
defined class Foo
scala> Foo().copy()
<console>:8: error: value copy is not a member of Foo
Foo().copy()
^
scala> case class Foo(x: Int)
defined class Foo
scala> Foo(0).copy()
res1: Foo = Foo(0)
Существует ли причина, почему компилятор делает это исключение? Я думаю, что это скорее unituitive, и я ожидал бы, что каждый класс случая определит метод копии.
Вторая проблема: у Меня есть метод def ops: List[Op]
и я хотел бы скопировать всю операцию в секунду как ops map { _.copy() }
. Как я определил бы метод копии в Op
черта? Я получаю "слишком много аргументы" ошибка, если я говорю def copy(): Op
. Однако начиная со всей копии () методы имеют только дополнительные аргументы: почему это неправильно? И, как я делаю, это исправляет? Путем создания другого метода назван def clone(): Op
и запишите везде def clone() = copy()
для всех классов случая?Надеюсь, что нет.
Методы копирования генерируются только в том случае, если в классе нет члена с именем "copy", определенного напрямую или унаследованного.
Похоже, вы путаете copy
с clone
. Цель копии
- сделать почти идентичную копию, но с чем-то измененным. Что это может быть за что-то, зависит от параметров класса case, поэтому невозможно сделать его общим методом.
В случае класса case X()
нет особого смысла в методе copy
, поскольку там нечего изменять.
С другой стороны, clone
- это метод Java, целью которого является создание идеальных копий объекта, что, похоже, является тем, что вам нужно.
Зачем вам создавать идентичные копии экземпляров класса case? Классы case по умолчанию являются неизменяемыми, поэтому к которым можно безопасно делиться.
В любом случае, я не думаю, что вы можете делать то, что вы просите, с параметрами по умолчанию:
scala> trait Op { def copy():Op }
defined trait Op
scala> case class Op1(v:Int) extends Op
<console>:6: error: class Op1 needs to be abstract, since method copy in trait Op of type ()Op is not defined
case class Op1(v:Int) extends Op
Компилятор не создает методы со всеми комбинациями необязательных параметров в определяющем классе. Значения по умолчанию вставляются в место вызова метода.
Проголосовал за ответ Бена. Но что если вы хотите сделать что-то вроде этого:
sealed trait Op
case class Push(value: Int, context:String) extends Op
case class Pop(context:String) extends Op
val stackOps = List(Push(3, "foo"), Pop("foo"))
def copyToContext(newContext:String, ops:List[Op]): List[Op] = {
// ... ?
}
val changedOps = copyToContext("bar", stackOps)
// would return: List(Push(3, "bar"), Pop("bar"))