Scala Type Erasure on case 类 如何解决
Scala Type Erasure on case classes how to solve
我有一个特征和两个扩展它的案例 classes:
trait Authenticatable {
val email: String
val pass: String
val id: Long
val sessionid: String
}
case class Admin(
id: Long,
email: String,
pass: String,
sessionid: Option[String] = None) extends Authenticatable
case class Client(
id: Long,
email: String,
pass: String,
sessionid: Option[String] = None) extends Authenticatable
我有一些功能 应该对用户进行身份验证,使用新的 sessionid 和 return 复制对象。
def auth(email: String, password: String): Try[Admin] ={
checkPass(models.Admin.findBy(sqls"email = $email"), password)
}
def auth(email: String, password: String, customer: Customer): Try[Customer] ={
checkPass(models.Customer.findBy(sqls"email = $email"), password)
}
private def checkPass (model: Option[Authenticatable], password: String): Try[Authenticatable]={
model match {
case Some(m) => check(password, m.pass).map(_ => m)
case _ => Failure(new Exception("Authentication failure!"))
}
}
问题是:我无法在 auth 函数中复制对象,因为函数 checkPass returns Authenticatable 而不是 Client 或 Admin class 并且 Authenticatable 没有 case 的复制方法classes.
解决这个问题的正确方法是什么?
我建议向 Authenticable
添加一个抽象方法,它设置会话 ID,并通过使用生成的 copy
方法由个别案例 类 实现。
trait Authenticable {
def email: String
def pass: String
def id: Long
def sessionid: Option[String]
def setSessionId(id: String): Authenticable
}
case class Admin(
id: Long,
email: String,
pass: String,
sessionid: Option[String] = None) extends Authenticable {
def setSessionId(id: String) = copy(sessionid = Some(id))
}
case class Client(
id: Long,
email: String,
pass: String,
sessionid: Option[String] = None) extends Authenticable {
def setSessionId(id: String) = copy(sessionid = Some(id))
}
如果您使用类型参数,您可以避免丢弃 checkPass
将始终 return 相同类型的 Authenticable
的信息:
private def checkPass[A <: Authenticatable](model: Option[A], password: String): Try[A] =
// exactly the same body here
这意味着在 auth
你可以有例如:
def auth(email: String, password: String): Try[Admin] =
checkPass(models.Admin.findBy(sqls"email = $email"), password)
.map(_.copy(sessionid = Some("whatever")))
我有一个特征和两个扩展它的案例 classes:
trait Authenticatable {
val email: String
val pass: String
val id: Long
val sessionid: String
}
case class Admin(
id: Long,
email: String,
pass: String,
sessionid: Option[String] = None) extends Authenticatable
case class Client(
id: Long,
email: String,
pass: String,
sessionid: Option[String] = None) extends Authenticatable
我有一些功能 应该对用户进行身份验证,使用新的 sessionid 和 return 复制对象。
def auth(email: String, password: String): Try[Admin] ={
checkPass(models.Admin.findBy(sqls"email = $email"), password)
}
def auth(email: String, password: String, customer: Customer): Try[Customer] ={
checkPass(models.Customer.findBy(sqls"email = $email"), password)
}
private def checkPass (model: Option[Authenticatable], password: String): Try[Authenticatable]={
model match {
case Some(m) => check(password, m.pass).map(_ => m)
case _ => Failure(new Exception("Authentication failure!"))
}
}
问题是:我无法在 auth 函数中复制对象,因为函数 checkPass returns Authenticatable 而不是 Client 或 Admin class 并且 Authenticatable 没有 case 的复制方法classes.
解决这个问题的正确方法是什么?
我建议向 Authenticable
添加一个抽象方法,它设置会话 ID,并通过使用生成的 copy
方法由个别案例 类 实现。
trait Authenticable {
def email: String
def pass: String
def id: Long
def sessionid: Option[String]
def setSessionId(id: String): Authenticable
}
case class Admin(
id: Long,
email: String,
pass: String,
sessionid: Option[String] = None) extends Authenticable {
def setSessionId(id: String) = copy(sessionid = Some(id))
}
case class Client(
id: Long,
email: String,
pass: String,
sessionid: Option[String] = None) extends Authenticable {
def setSessionId(id: String) = copy(sessionid = Some(id))
}
如果您使用类型参数,您可以避免丢弃 checkPass
将始终 return 相同类型的 Authenticable
的信息:
private def checkPass[A <: Authenticatable](model: Option[A], password: String): Try[A] =
// exactly the same body here
这意味着在 auth
你可以有例如:
def auth(email: String, password: String): Try[Admin] =
checkPass(models.Admin.findBy(sqls"email = $email"), password)
.map(_.copy(sessionid = Some("whatever")))