Scala - 模式匹配相关类型的元组
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11986892/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Scala - pattern-matching a tuple of related types
提问by noncom
I have the following class hierarchy:
我有以下类层次结构:
class A
class B extends A
class C extends A
then, there is another class which takes instances of these classes and there is a method, in which two cases of pattern-matching are possible like this:
然后,还有另一个类接受这些类的实例,并且有一个方法,其中可能有两种模式匹配,如下所示:
class D (one: A, two: A) {
def work {
(one, two) match {
case (o, t): (B, B) => ... blablabla
case (o, t): (B, C) => ... blablabla
case _ =>
}
}
}
However, when it should resolve the matching in favor of the second case (B, C), it tries resolving it as (B, B)and comes up with the class cast exception that C cannot be cast to B. Why? What to do? How can I come around this?
但是,当它应该解析匹配以支持第二种情况时(B, C),它会尝试将其解析为 as(B, B)并提出类转换异常 that C cannot be cast to B。为什么?该怎么办?我怎样才能解决这个问题?
回答by Brian Smith
Your syntax isn't quite right (doesn't compile).
您的语法不太正确(无法编译)。
This works though:
这虽然有效:
object Matcher extends App {
class A
class B extends A
class C extends A
class D(one: A, two: A) {
def work {
(one, two) match {
case (o: B, t: B) => println("B")
case (o: B, t: C) => println("C")
case _ =>
}
}
}
val d1 = new D(new B, new B)
val d2 = new D(new B, new C)
d1.work
//B
d2.work
//C
}
回答by Submonoid
The problem, as always, is erased types. (B,C)is syntactic sugar for Tuple2[B,C], which is erased to Tuple2at runtime. The case statement verifies that (B,C)matches Tuple2, but then fails to cast it.
与往常一样,问题是擦除类型。(B,C)是 的语法糖Tuple2[B,C],它Tuple2在运行时被擦除。case 语句验证(B,C)匹配Tuple2,但随后无法转换它。
In your case, the easiest solution would be to match against 'one' and 'two' individually, rather than wrapping them in a tuple:
在您的情况下,最简单的解决方案是分别匹配“一”和“二”,而不是将它们包装在一个元组中:
one match {
case o : B => two match {
case p : C => ...
case p : B => ...
}
...
}
It's not so pretty, but it won't suffer from the same problems.
它不是那么漂亮,但它不会遇到同样的问题。
Edit: Actually, I'd go with Brian Smith's solution - matching inside the tuple rather than outside. It avoids the problem in a similar way, but looks nicer.
编辑:实际上,我会采用 Brian Smith 的解决方案 - 在元组内部而不是外部匹配。它以类似的方式避免了这个问题,但看起来更好。
回答by tgr
I made this code work.
Firstly I added a case to your class definition.
我让这段代码工作。
首先,我在您的类定义中添加了一个案例。
case class A
case class B extends A
case class C extends A
Secondly I changed the work.
其次,我改变了work.
class D(one: A, two: A) {
def work {
(one, two) match {
case (o: B, t: B) => println("BB")
case (o: B, t: C) => println("BC")
case (o: C, t: C) => println("CC")
case _ => println("AA")
}
}
}
Now what I got:
现在我得到了什么:
new D(B(),B()).work => BB
new D(B(),C()).work => BC
new D(C(),C()).work => CC
new D(A(),B()).work => AA
The caseadds an apply and an unapply method.
在case增加了一个适用和不应用方法。

