Мне нужен конкретный пример того, как определить локальный параметр в основном конструкторе неизменяемого класса _case_

У меня есть обычный класс Scala, который я хочу реорганизовать, чтобы он стал неизменяемым классом case. Поскольку мне нужно, чтобы класс хорошо вел себя в Set операциях, я хочу, чтобы все методы, автоматически сгенерированные компилятором Scala, предоставлялись для класса case. IOW, я хочу избежать написания этих различных методов; equals, hashCode, toString и т. Д., Поскольку это очень подвержено ошибкам. И мне нужно сделать это для множества классов, поэтому мне нужно общее решение, а не просто конкретное решение аномального быстрого исправления или взлома.

Вот класс, с которым я работаю:

class Node(val identity: String, childrenArg: List[Node], customNodeArg: CustomNode) {
  val children: List[Node] = childrenArg
  val customNode: CustomNode = customNodeArg
}

Как видите, конструктор класса имеет три параметра. Первый, identity, доступен только для чтения. Остальные два, childrenArg и customNodeArg, являются обычными параметрами метода; т.е. они присутствуют только во время создания экземпляра, а затем полностью исчезают из экземпляра класса (если иное не зафиксировано) по завершении выполнения конструктора класса.

Моя первая наивная попытка преобразовать это в неизменяемый класс case была следующая (просто удалив val из первого параметра):

class Node(identity: String, childrenArg: List[Node], customNodeArg: CustomNode) {
  val children: List[Node] = childrenArg
  val customNode: CustomNode = customNodeArg
}

Однако это привело к нежелательному эффекту от того, что оба параметра childrenArg и customNodeArg теперь были повышены, чтобы стать (доступными только для чтения) свойствами (вместо того, чтобы оставить их как обычные параметры метода). И это имело еще один нежелательный эффект - они были включены в составленные компилятором реализации equals и hashCode.

Как пометить неизменяемые параметры конструктора класса case childrenArg и customNodeArg так, чтобы identity было единственным свойством класса case, доступным только для чтения?

Любые указания по этому поводу; ответы, ссылки на обсуждения на веб-сайте и т. д. приветствуются.


person chaotic3quilibrium    schedule 22.03.2016    source источник
comment
Речь идет конкретно о классе Scala case, а не об общем классе Scala. IOW, это НЕ дубликат других вопросов StackOverflow: stackoverflow.com/q/1889454/501113   -  person chaotic3quilibrium    schedule 22.03.2016


Ответы (2)


Второй список параметров, кажется, помогает:

scala> trait CustomNode
defined trait CustomNode

scala> case class Node(identity: String)(childrenArg: List[Node], customNodeArg: CustomNode)
defined class Node

scala> val n = Node("id")(Nil, null)
n: Node = Node(id)

scala> n.identity
res0: String = id

scala> n.getClass.getDeclaredFields.map(_.getName)
res1: Array[String] = Array(identity)
person Jean-Philippe Pellet    schedule 22.03.2016
comment
Это ИМЕННО то решение, которое я искал! Tysvm! Scala НАСТОЛЬКО гибкая, временами я не вижу решения. Я знал о дополнительных списках аргументов. Я просто никогда не видел и не думал использовать их таким образом. Потрясающий! - person chaotic3quilibrium; 23.03.2016
comment
Я использовал ваше решение, отвечая на другой вопрос StackOverflow, связанный с поиском циклов в ориентированном графе. Я использовал его в абстрактном классе case внизу ответа: stackoverflow.com/a/36144158/501113 - person chaotic3quilibrium; 23.03.2016

Параметры класса case по умолчанию - vals, но вы можете установить их в vars.

case class Node(identity: String, var childrenArg: List[Node], var customNodeArg: CustomNode)

Создание их варов автоматически дает вам геттеры и сеттеры

person redeagle47    schedule 22.03.2016
comment
Я не думаю, что это не решит мою проблему, поскольку параметры childrenArg и customNodeArg по-прежнему являются свойствами; т.е. они включены в сгенерированные компилятором реализации функций equals и hashCode. И хотя это подразумевалось (и я отредактировал свой вопрос, чтобы теперь сделать его явным), мне нужно, чтобы класс case был неизменным. А наличие любых var параметров делает класс case изменяемым. - person chaotic3quilibrium; 22.03.2016