Копия класса случая () абстракция метода

Я хотел бы знать, возможно ли абстрагировать метод копии классов случая. В основном у меня есть что-то как 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() для всех классов случая?Надеюсь, что нет.

12
задан Joa Ebert 26 May 2010 в 09:29
поделиться

4 ответа

  1. Какова польза от сгенерированного компилятором метода копирования для классов case без аргументов? Он бы просто возвращал новый Foo и ничего не копировал.
  2. Чтобы процитировать Лукаса Рытца (я полагаю, он это реализовал):
Методы копирования генерируются только в том случае, если в классе нет члена с именем "copy", определенного напрямую или унаследованного.
9
ответ дан 2 December 2019 в 06:07
поделиться

Похоже, вы путаете copy с clone. Цель копии - сделать почти идентичную копию, но с чем-то измененным. Что это может быть за что-то, зависит от параметров класса case, поэтому невозможно сделать его общим методом.

В случае класса case X() нет особого смысла в методе copy, поскольку там нечего изменять.

С другой стороны, clone - это метод Java, целью которого является создание идеальных копий объекта, что, похоже, является тем, что вам нужно.

12
ответ дан 2 December 2019 в 06:07
поделиться

Зачем вам создавать идентичные копии экземпляров класса 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

Компилятор не создает методы со всеми комбинациями необязательных параметров в определяющем классе. Значения по умолчанию вставляются в место вызова метода.

1
ответ дан 2 December 2019 в 06:07
поделиться

Проголосовал за ответ Бена. Но что если вы хотите сделать что-то вроде этого:

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"))
1
ответ дан 2 December 2019 в 06:07
поделиться
Другие вопросы по тегам:

Похожие вопросы: