【问题标题】:Scala Type Erasure on case classes how to solve案例类上的Scala Type Erasure如何解决
【发布时间】:2015-09-09 03:52:48
【问题描述】:

我有一个 trait 和两个扩展它的 case 类:

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 复制对象并返回它。

  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 返回 Authenticatable 而不是 Client 或 Admin 类,并且 Authenticatable 没有案例类的复制方法。

解决这个问题的正确方法是什么?

【问题讨论】:

    标签: scala implicit


    【解决方案1】:

    如果您使用类型参数,您可以避免丢弃checkPass 将始终返回与提供给它的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")))
    

    【讨论】:

      【解决方案2】:

      我建议向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))
      }
      

      【讨论】:

      • 谢谢。这是可能的答案,但我更喜欢另一个
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-07-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多