Как переопределить атрибут класса case и избежать дублирования хранилища? - PullRequest
1 голос
/ 25 мая 2019

У меня есть сценарий использования, который использовал бы преимущество переопределения атрибута класса случая, если бы это было возможно в Scala 2.12.x.Мой вариант использования следующий: в Play-Silhouette (PS), например, LoginInfo, на котором построена библиотека, есть несколько классов наблюдений:

case class LoginInfo(providerID: String, providerKey: String)

Если жизнь будетидеально, это были бы признаки, а не классы дел, но хорошо, теперь в проекте, который повторно использует PS, я хотел бы спроектировать мою базу данных, настроить генератор кода Slick и получить совместимые с базой данных определения Slick-mapped для этих классов дел PSнапример,

case class LoginInfoRow(id: Int, override val providerID: String, override val providerKey: String, modified: Option[java.sql.Timestamp] = None) 
  extends com.mohiva.play.silhouette.api.LoginInfo(providerID, providerKey)

Этот подход позволил бы мне без проблем подключить мой специализированный Slick-Persistence LoginInfoRow к платформе PS.Обратите внимание, что это автоматически генерируется из базы данных, используя Slick + мой пользовательский генератор изменений.Приведенное выше определение LoginInfoRow приводит к ошибке компилятора:

[error] /home/skywalker/code/play-silhouette-seed/app/models/generated/Tables.scala:29:14: case class LoginInfoRow has case ancestor com.mohiva.play.silhouette.api.LoginInfo, but case-to-case inheritance is prohibited. To overcome this limitation, use extractors to pattern match on non-leaf nodes.
[error]   case class LoginInfoRow(id: Int, override val providerID: String, override val providerKey: String, modified: Option[java.sql.Timestamp] = None) extends com.mohiva.play.silhouette.api.LoginInfo(providerID, providerKey)
[error]              ^
[error] one error found
[error] (Compile / compileIncremental) Compilation failed
[error] Total time: 3 s, completed May 25, 2019 12:06:43 PM

Возможное решение состоит в том, чтобы иметь разные имена для этих двух атрибутов, но это может привести к путанице в интерфейсе LoginInfoRow, которыйиспользовать?и это также дублировало бы хранилище.

Что предлагает этот компилятор альтернативу To overcome this limitation, use extractors to pattern match on non-leaf nodes.?

1 Ответ

1 голос
/ 25 мая 2019

Вы можете написать неявный или явный конвертер для этого сценария.

Неявный преобразователь:

implicit def loginInfoRowToLoginInfo(loginInfoRow: LoginInfoRow): LoginInfo = {
  LoginInfo(loginInfoRow.providerID, loginInfoRow.providerKey)
}

Явный конвертер:

case class LoginInfoRow(
  id: Int,
  providerID: String,
  providerKey: String,
  modified: Option[java.sql.Timestamp] = None
) {
  def toSilhouette: LoginInfo = {
    LoginInfo(providerID, providerKey)
  }
}

Или комбинация обоих.

...