Scala简单多态性

时间:2014-02-07 07:41:24

标签: scala generics polymorphism

我需要一个公共(通用?)接口JsonModel来处理类“Processor”来处理JsonModel派生类。为什么下面的代码不起作用?

trait JsonModel
case class LoginInfo(userid: Int, email: String, password: String) extends JsonModel
class Processor(command: String, content: String) {

  def makeLoginInfo : JsonModel = content.asJson.convertTo[LoginInfo]//Spray library

  def process = {
   command match {
     case "logininfo" => makeLoginInfo
     case _ => throw new IllegalArgumentException("Unknow command")//TODO: Replace to log
   }
  }
}
def addUser(content: String) = {val loginInfo : LoginInfo = new Processor("logininfo", content).process}

错误消息是:

type mismatch;
found   : JsonModel
required: LoginInfo
   val loginInfo : LoginInfo = new Processor("logininfo", content).process
                                                                ^

1 个答案:

答案 0 :(得分:1)

您正尝试从基类JsonModel隐式转换为派生类LoginInfo。通过匹配将JsonModel投射到LoginInfo

val loginInfo: Option[LoginInfo] = new Processor("logininfo", command).process match {
    case l: LoginInfo => Some(l)
    case _ => None
}

如果您使用Option[LoginInfo],那么也可以使用Scala的idomatic错误处理。否则,您仍然可以使用null

要以错误安全的方式访问成员,您应该使用monad函数。 (这些也适用于理解。)

option map { _.data_value } getOrElse fallback_value

// OR... for particularly long operations
(for (inner <- option) yield inner.data_value) getOrElse fallback_value

或者,您可以makeLoginInfo返回LoginInfo;但是,一旦您将JsonModel派生的其他元素添加到process的返回列表中,您将再次遇到此问题。

修改

另一种可能性是使用NoLoginInfo对象。

class NoLoginInfo(u: Int, e: String, p: String) extends LoginInfo(u, e, p) {
    // Override and Pretend Functionality
}
val loginInfo: LoginInfo = new Processor("logininfo", command).process match {
    case l: LoginInfo => l
    case _ => new NoLoginInfo("not a user", "not an email", "not a password")
}