Вопрос или проблема
Я пытаюсь использовать пользовательский метод apply в компаньон-объекте case-класса, чтобы создать экземпляр User без необходимости вручную указывать ID. ID должен автоматически генерироваться с использованием AtomicLong. Однако я получаю ошибку с сообщением:
missing argument for parameter id of method apply in object User: (id: Long, email: String, login: String, firstname: String, lastname: String, password: String): User
Вот мой case-класс и компаньон-объект:
case class User private(id: Long, email: String, login: String, firstname: String, lastname: String, password: String)
object User {
private val seq = new AtomicLong
def apply(email: String, login: String, firstname: String, lastname: String, password: String): User = {
new User(seq.incrementAndGet(), email, login, firstname, lastname, password)
}
def mapperTo(id: Long, email: String, login: String, firstname: String, lastname: String, password: String): User = {
new User(id, email, login, firstname, lastname, password)
}
}
В моем контроллере я пытаюсь создать User без указания ID:
def createUser = Action { implicit request: MessagesRequest[AnyContent] =>
//lazy val usersTable = TableQuery[UserTable]
val db = Database.forConfig("sqlite")
val errorFunction = { (formWithErrors: Form[Data]) =>
formWithErrors.errors.foreach { error =>
println(s"Ошибка в поле: ${error.key}, сообщение: ${error.message}")
}
BadRequest(views.html.signup(formWithErrors))
}
val successFunction = { (data: Data) =>
// Это хороший случай, когда форма была успешно обработана как объект Data.
val user = User.apply(email = data.email, login = data.login, firstname = data.firstname, lastname = data.lastname, password = data.password)
val insertQuery = usersTable += user
UserDatabase.db.run(insertQuery)
Redirect(routes.HomeController.index()).flashing("info" -> "Новый пользователь")
}
val formValidationResult = form.bindFromRequest()
formValidationResult.fold(errorFunction, successFunction)
}
Но я получаю ошибку на строке, где пытаюсь создать User. Кажется, что Scala ищет параметр id, несмотря на то, что я хочу использовать метод apply, который генерирует его внутренне.
У меня также есть метод mapperTo в компаньон-объекте для отображения данных из базы данных, но это не должно влиять на метод apply.
Что может вызывать у Scala запрос id при вызове apply, и как я могу решить эту проблему?
Ответ или решение
Проблема, с которой вы сталкиваетесь, связана с тем, как Scala обрабатывает методы в companion object для case class. Давайте разберем вашу ситуацию.
- Ошибка "missing argument for parameter id" указывает на то, что компилятор Scala не может найти ваш пользовательский метод
apply
, и вместо этого ожидает стандартного методаapply
, который автоматически создается для case class. Этот стандартный метод требует все параметры, включаяid
, поскольку он генерируется на основе определения case class.
Чтобы это исправить, вы можете сделать следующее:
-
Переименуйте метод apply: Ваша проблема может быть решена не изменением метода
apply
, а добавлением явного указания на то, что вы хотите использовать вашу собственную версию методаapply
. В данном случае, методapply
синтаксически перегружен, и Scala не определяет, какой именно метод вам нужен при вызове. -
Используйте явное указание: Вместо вызова
User.apply(...)
, просто используйтеUser(...)
, чтобы вызвать ваш собственный методapply
. Также не забудьте убедиться, что у вас корректные импорты для работы с вашим классом.
Вот ваши исправленные фрагменты кода:
case class User private(id: Long, email: String, login: String, firstname: String, lastname: String, password: String)
object User {
private val seq = new AtomicLong
// Ваш собственный метод apply
def apply(email: String, login: String, firstname: String, lastname: String, password: String): User = {
new User(seq.incrementAndGet(), email, login, firstname, lastname, password)
}
def mapperTo(id: Long, email: String, login: String, firstname: String, lastname: String, password: String): User = {
new User(id, email, login, firstname, lastname, password)
}
}
И в контроллере, замените вызов на:
val user = User(data.email, data.login, data.firstname, data.lastname, data.password)
Обратите внимание, что здесь используется User(...)
, что указывает на вызов вашего метода apply
. Это должно устранить проблему с отсутствием параметра id
и позволить вам создавать экземпляры User
, не указывая уникальный id явно.
После этих изменений ваш код должен работать исправно, и ошибка должна исчезнуть. Если у вас возникнут дополнительные вопросы или потребуются уточнения, не стесняйтесь задавать!