我可以通过匹配该对象的字段来匹配整个Scala Object
吗?
想象一下,我有一个trait Command
,其中有一个字段def name: String
。我有这个特征的几个对象。 Ls
,Cd
,Mkdir
,Echo
等。这些对象中的每一个都有绑定到name
的特定字符串。
例如
Mkdir.name = "mkdir", Cd.name = "cd".
现在,我从外部系统收到一个名为input
的字符串。我想匹配此字符串以获取这些对象之一。只是我不想有多个case子句,每个对象一个。这是因为,我正在对这些命令的不同子集进行验证。
我的代码如下:
input match {
case o @ (Mkdir.name | Cd.name | Rm.name) => // Some common code to run and return the matched Command (not string)
...
}
问题在于,在每种情况下,我需要知道输入所匹配的是哪个Command的名称。我无法用这段代码知道这一点,因为在这里,我只将一个字符串匹配为一个字符串的并集,从而在这里丢失了与该字符串匹配的对象(命令)的上下文。
所以,最终我的问题是我可以通过在一个字段上进行匹配来匹配对象吗?
答案 0 :(得分:1)
自定义提取器是这种用例的朋友。
object IsCommand {
def unapply(input: String) : Option[Command] = input.toLowerCase match {
case Ls.name => Some(Ls)
case Mkdir.name => Some(Mkdir)
case Rm.name => Some(Rm)
...
case _ => None
}
}
您现在可以按照以下方式进行模式匹配:
"ls" match {
case IsCommand(command) => ... // command will be the object Ls
}
我不确定是否可以通过不使用宏之类的方法来缩短unapply
方法中的代码,但是在任何情况下,您只需编写一次即可。
答案 1 :(得分:0)
作为Astrid提出的解决方案的替代方案,您可以创建CommandExtractor
,它将用作参数化提取器,然后创建用于模式匹配的实例:
class CommandExtractor(commands: Command*) {
def unapply(name: String): Option[Command] = commands.find(_.name == name)
}
val MkdirOrEcho = CommandExtractor(Mkdir, Echo)
val RmOrCdOrPwd = CommandExtractor(Rm, Cd, Pwd)
input match {
case MkdirOrEcho(c) => ??? // matching Mkdir or echo
case RmOrCdOrPwd(c) => ??? //matching rm, cd or pwd
}
这样做的缺点是您丢失了有关正在接收哪个命令的信息,但是由于您已经需要在一个分支中匹配多个命令,因此您可能不需要该信息。