Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

trait 中 case class #14

Open
zhongl opened this issue Aug 23, 2013 · 1 comment
Open

trait 中 case class #14

zhongl opened this issue Aug 23, 2013 · 1 comment
Labels

Comments

@zhongl
Copy link
Member

zhongl commented Aug 23, 2013

注意, 以下代码都以在 scala 2.10.2 jdk 1.7中编译运行为讨论前提

trait A {
  case class B(i: Int)
}

class C extends A {
  def !(a:Any) = a match {
    case B(0) => println("never be here")
    case b: B => println("never be here")
    case x    => println(s"Oops, received $x")
  }
}

class D extends A {
  new C ! B(0)
}

new D

上面代码在 scala REPL 中运行, 打印输出的结果是Oops, received B(0), 问题就出来了:

为什么case B(0)case b: B都没有能够匹配上?

问题的答案可以从scalac -Xprint:typer结果中找到:

 class C extends AnyRef with A {
    def <init>(): C = {
      C.super.<init>();
      ()
    };
    def !(a: Any): Unit = a match {
      case (i: Int)C.this.B(0) => scala.this.Predef.println("never be here")
      case (b @ (_: C.this.B)) => scala.this.Predef.println("never be here")
      case (x @ _) => scala.this.Predef.println(scala.StringContext.apply("Oops, received ", "").s(x))
    }
  };

  class D extends AnyRef with A {
    def <init>(): D = {
      D.super.<init>();
      ()
    };
    new C().!(D.this.B.apply(0))
  }

new C ! B(0)B的类型是D.this.B, 而在C.!(a: Any)matchB的类型都是C.this.B

那么答案也就很明确了, 引用之 @hongjiang 的论断:

这个 case 类是个内部类,这点性质与java一样,它一定要存活在它的外部对象实例内,外部实例不同,它们也不同

因此, 在实际应用中, 请谨慎使用这种用法, 除非你有特别好的理由


进一步的思考: Scala 编译器是如何实现的呢?

答案在这里, 你找找看:)

@zhongl
Copy link
Member Author

zhongl commented Aug 30, 2013

还可以参考http://hongjiang.info/scala-pitfalls-6/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant