1

如果在 Scala 2.12.x 中可行,我有一个用例可以利用案例类属性覆盖。我的用例如下: Play-Silhouette (PS)中有多个案例类,例如LoginInfo该库是基于:

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

如果生活是完美的,这些将是特征而不是案例类,但是好的,现在在一个重用 PS 的项目中,我想设计我的数据库,自定义 Slick 代码生成器并获得 Slick 映射的数据库友好定义那些 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.什么?

4

1 回答 1

1

您可以为这种情况编写一个隐式或显式转换器。

隐式转换器:

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)
  }
}

或两者兼而有之。

于 2019-05-25T11:28:04.863 回答