2011-08-10 42 views
6

根据阶规范,通过案例课的提取是以下(斯卡拉规范第5.3.2节):提出提取和案例类提取

def unapply[tps](x: c[tps]) = 
    if (x eq null) scala.None 
    else scala.Some(x.xs11, ..., x.xs1k) 

由于实现的原因,我想能够模仿这个提取器在非案例类上的行为。 但是,我的实现无法重现相同的行为。

这里是差的一个例子我有:

trait A 

sealed trait B[X <: A]{ val x: X } 

case class C[X <: A](x: X) extends B[X] 

class D[X <: A](val x: X) extends B[X] 

object D { 
    def unapply[X <: A](d: D[X]): Option[X] = 
    if (d eq None) None 
    else Some(d.x) 
} 

def ext[X <: A](b: B[X]) = b match { 
    case C(x) => Some(x) 
    case D(x) => Some(x) 
    case _ => None 
} 

我有以下警告:

<console>:37: warning: non variable type-argument X in type pattern D[X] is unchecked since it is eliminated by erasure 
    case D(x) => Some(x) 

通知警告仅发生在D情况下,而不是在壳体级textractor案件。 您是否对警告的原因有任何了解/关于我应该如何避免此警告?

注:如果你想测试它在REPL,最简单的方法是:

  1. 要激活选中警告

    斯卡拉>:电源

    斯卡拉> settings.unchecked .value = true

  2. 要以粘贴模式复制上述代码:

    阶>:粘贴

    [复制/粘贴]

    [CTRL + d]

编辑:作为Antoras提到它应该是编译器故障,也许阶版本可能是有用的:斯卡拉2.9.0.1 (快速测试后,在斯卡拉2.9.1RC2仍然存在)

回答

2

这似乎是一个编译器错误。我分析了编译器AST的输出(使用fsc -Xprint:typer <name_of_file>.scala)。它将两者解释为相同:

... 
    final <synthetic> object C extends java.lang.Object with ScalaObject with Serializable { 
     def this(): object test.Test.C = { 
     C.super.this(); 
     () 
     }; 
     final override def toString(): java.lang.String = "C"; 
     case <synthetic> def unapply[X >: Nothing <: test.Test.A](x$0: test.Test.C[X]): Option[X] = if (x$0.==(null)) 
     scala.this.None 
     else 
     scala.Some.apply[X](x$0.x); 
     case <synthetic> def apply[X >: Nothing <: test.Test.A](x: X): test.Test.C[X] = new test.Test.C[X](x); 
     protected def readResolve(): java.lang.Object = Test.this.C 
    }; 
... 
    final object D extends java.lang.Object with ScalaObject { 
     def this(): object test.Test.D = { 
     D.super.this(); 
     () 
     }; 
     def unapply[X >: Nothing <: test.Test.A](d: test.Test.D[X]): Option[X] = if (d.eq(null)) 
     scala.None 
     else 
     scala.Some.apply[X](d.x) 
    }; 
... 

这两种方法的方法签名不适用都是相同的。

而且(如预期,由于相同的方法)的代码工作正常:

trait A { 
    def m = "hello" 
} 

class AA extends A 

sealed trait B[X <: A]{ val x: X } 

case class C[X <: A](x: X) extends B[X] 

class D[X <: A](val x: X) extends B[X] 

object D { 
    def apply[X <: A](x: X) = new D(x) 
    def unapply[X <: A](d: D[X]): Option[X] = 
    if (d eq null) None 
    else Some(d.x) 
} 

def ext[X <: A](b: B[X]) = b match { 
    case C(x) => Some("c:"+x.m) 
    case D(x) => Some("d:"+x.m) 
    case _ => None 
} 
println(ext(C[AA](new AA()))) 
println(ext(D[AA](new AA()))) 
+0

你认为我们有足够的材料来开罚单? – Nicolas

+0

是的,我认为这就够了。有一个警告,但代码工作正常。此外,生成的代码也可以正常工作并且完全相同。 – sschaef