假設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這樣的單線程上下文中顯示這個例子嗎?不是我不相信這個相關案例。 –