“Отсутствует аргумент для параметра id” при вызове apply в伴随 становом классе

Вопрос или проблема

Я пытаюсь использовать пользовательский метод 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. Давайте разберем вашу ситуацию.

  1. Ошибка "missing argument for parameter id" указывает на то, что компилятор Scala не может найти ваш пользовательский метод apply, и вместо этого ожидает стандартного метода apply, который автоматически создается для case class. Этот стандартный метод требует все параметры, включая id, поскольку он генерируется на основе определения case class.

Чтобы это исправить, вы можете сделать следующее:

  1. Переименуйте метод apply: Ваша проблема может быть решена не изменением метода apply, а добавлением явного указания на то, что вы хотите использовать вашу собственную версию метода apply. В данном случае, метод apply синтаксически перегружен, и Scala не определяет, какой именно метод вам нужен при вызове.

  2. Используйте явное указание: Вместо вызова 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 явно.

После этих изменений ваш код должен работать исправно, и ошибка должна исчезнуть. Если у вас возникнут дополнительные вопросы или потребуются уточнения, не стесняйтесь задавать!

Оцените материал
Добавить комментарий

Капча загружается...