假设Foo
是一个简单的案例类,下列表达式的值是什么情况下是2
?奇怪模式匹配问题
Option(myFoo) match {
case Some(x: Foo) => 1
case Some(x) if x.isInstanceOf[Foo] => 2
case _ => 3
}
查看Loss of type info in servlet code查看该问题的上下文。
假设Foo
是一个简单的案例类,下列表达式的值是什么情况下是2
?奇怪模式匹配问题
Option(myFoo) match {
case Some(x: Foo) => 1
case Some(x) if x.isInstanceOf[Foo] => 2
case _ => 3
}
查看Loss of type info in servlet code查看该问题的上下文。
第一和第二种情况是等价的。
这里是你的功能反编译回Java(使用scala-to-java):
斯卡拉:
type Foo = String
def test(foo:Any) = Option(foo) match {
case Some(x: Foo) => 1
case Some(x) if x.isInstanceOf[Foo] => 2
case _ => 3
}
的Java:
import scala.*;
public final class _$$anon$1 {
private int test(final Object foo) {
boolean b = false;
Some<Object> some = null;
final Option<Object> apply = Option$.MODULE$.apply(foo);
if (apply instanceof Some) {
b = true;
some = (Some<Object>)apply;
final Object x = some.x();
if (x instanceof String) {
return 1;
}
}
if (b) {
final Object x2 = some.x();
if (x2 instanceof String) {
return 2;
}
}
return 3;
}
}
更新!
看来,模式匹配原理不同的内部类:
case class Wrapper(wrapped: String)
def test(a:Any) = Option(a) match {
case Some(x:Wrapper) => x
case Some(x) if x.isInstanceOf[Wrapper] => x
case x => ???
}
可生产这样的事情:
private Object test(final Object a) {
boolean b = false;
Some<Object> some = null;
final Option<Object> apply = Option$.MODULE$.apply(a);
if (apply instanceof Some) {
b = true;
some = (Some<Object>)apply;
final Object x = some.x();
if (x instanceof _$$anon$1$Wrapper && ((_$$anon$1$Wrapper)x)._$$anon$Wrapper$$$outer() == this) {
return x;
}
}
if (b) {
final Object x2 = some.x();
if (x2 instanceof _$$anon$1$Wrapper) {
return x2;
}
}
throw Predef$.MODULE$.$qmark$qmark$qmark();
}
所以,它还会检查“外”领域,即外部类。如果你不能控制自己的环境,比如你无法保证外部类总是同一个实例,那么模式匹配可能会失败(这很让人不快发现)。
感谢您的回答!这真的很奇怪 - 但这并不意味着它应该无法访问?我有一些代码,绝对匹配第二种情况。我已经在https://github.com/kardeiz/sc-issue-20160229/上提供了一个简单的例子,如果你或其他人愿意看看 –
@kardeiz请检查更新。 – Aivean
哇,棘手!尽管我猜测这很有道理。非常感谢您的追踪! –
在x不是Foo类的实例的情况下,说任何类型但Foo类型。但是对不起,如果x.isInstanceOf [Foo]使case 1和case2是相同的情况,那么在任何情况下都不会是2。 假设你有这个代码
def f(t:Any) = Option(t) match {
case Some(x: Foo) => 1
case Some(x) if x.isInstanceOf[Foo] => 2
case _ => 3
}
用例可能与您链接的内容不可分离。也就是说,你可能不能在像REPL这样的单线程上下文中显示这个例子吗?不是我不相信这个相关案例。 –