我需要一个公共(通用?)接口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
^
答案 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")
}