Skip to content

trait 中 case class  #14

@zhongl

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 编译器是如何实现的呢?

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

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