[英]Scala pattern match multiple types
I have a code for extracting Int
from JValue
that should look exactly the same for multiple JValue
subclasses, so I'm trying to avoid repeating myself. 我有一个从JValue
中提取Int
的代码,对于多个JValue
子类应该看起来完全相同,所以我试图避免重复自己。 However, as it is (see below), scala thinks that j
is a generic JValue
, and that j.values
returns a value of type Values
, which, of course, does not have isValidInt
and toInt
methods. 但是,正如它(见下文)所示,scala认为j
是一个通用的JValue
,而j.values
返回的是Values
类型的Values
,当然,它没有isValidInt
和toInt
方法。
jvalue \ name match {
case j @ (JInt | JDecimal | JDouble) => {
val num = j.values
if (num.isValidInt) num.toInt.success else reportError(name + " is not a valid int")
}
The question is what is the proper way to avoid repetition here? 问题是避免重复的正确方法是什么? I'm not that crazy about converting a JValue
into string, because this code works with json just parsed from a string into an AST. 我对将JValue
转换为字符串并不是那么疯狂,因为这段代码只是将json从字符串解析为AST。 I started thinking about writing wrappers for the three types I need matched and implicit converters from these types into wrappers, and then making a superclass just for these wrappers for use as a pattern, but I am not sure how to pull it off. 我开始考虑为我需要匹配的三种类型编写包装器,并将这些类型的隐式转换器编写为包装器,然后为这些包装器创建一个超类用作模式,但我不知道如何将它拉下来。
And yes, I realize there are multiple similar questions here (such as this and this ), but each of them only contains part of the solution at most. 是的,我知道这里有多个类似的问题(比如这个和这个 ),但每个问题最多只包含部分解决方案。
Implement an extractor to get the Int
value out of arbitrary json values, then use the extractor in your mattern match. 实现一个提取器以从任意json值中获取Int
值,然后在mattern匹配中使用提取器。
object JsonInt {
def unapply(json: JValue): Option[Int] = json match {
case JInt(i) if i.isValidInt => Some(i.toInt)
case JDecimal(d) if d.isValidInt => Some(d.toInt)
case JDouble(d) if d.isValidInt => Some(d.toInt)
case _ => None
}
}
jvalue \ name match {
case JsonInt(num) => num.success
case _ => reportError(s"$name is not a valid int")
}
Scala has only limited support for structural typing. Scala对结构类型的支持有限。 Seems like JValue
is the lowest common ancestor of these three types. 似乎JValue
是这三种类型中最低的共同祖先。 If you want, you may get around it by defining an implicit conversion from JValue
to some wrapper class that will have isValidInt
method. 如果需要,可以通过定义从JValue
到具有isValidInt
方法的某个包装类的隐式转换来解决它。
If you don't bother using structural typing, you can use asInstanceOf
method to be able to use toInt
and isValidInt
method: 如果您不打扰使用结构类型,可以使用asInstanceOf
方法来使用toInt
和isValidInt
方法:
type IntExt = {
def toInt: Int
def isValidInt: Boolean
}
jvalue \ name match {
case j @ (_: JInt | _: JDecimal | _: JDouble) =>
val num = j.values.asInstanceOf[IntExt]
if (num.isValidInt) num.toInt.success else reportError(name + " is not a valid int")
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.