Skip to content

trait 中 case class  #14

Description

@zhongl

注意, 以下代码都以在 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 编译器是如何实现的呢?

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

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions