2011-08-10 4 views
6

を作っ:違いは、Scalaの仕様によると、ケースクラスによって構築された抽出には、次の(Scalaの仕様§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 
} 

私は次の警告があります:警告のみD場合、ない場合、クラスで発生し

<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) 

お知らせテキスタイルケース。 警告の原因について/私がこの警告を避けるために何をすべきかについて考えていますか?

注:あなたがREPLでそれをテストしたい場合はは、最も簡単な方法は次のとおりです。

  1. は未チェックの警告を有効にするには

    スカラ>:パワー

    スカラ> settings.unchecked .value = true

  2. 上記のコードを貼り付けモードでコピーする:

    スカラ>:Antorasが、それはコンパイラのバグ、多分Scalaのバージョンでなければなりません述べたように:

    [コピー/貼り付け]

    [CTRL + D]

編集を貼り付けscala 2.9.0.1 (クイックテスト後、まだscala 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

関連する問題