2011-08-10 19 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 मामले में होता है मामला श्रेणी में नहीं टेक्स्टट्रैक्टर केस क्या आपको चेतावनी के कारण/इस चेतावनी से बचने के लिए मुझे क्या करना चाहिए इसके बारे में कोई जानकारी है?

नोट: आप आरईपीएल में यह परीक्षण करना चाहते हैं, सबसे आसान तरीका है:

  1. अनियंत्रित चेतावनी सक्रिय करने के लिए

    स्केला>: बिजली

    स्केला> settings.unchecked .value = true

  2. पेस्ट मोड में उपरोक्त कोड की प्रतिलिपि बनाने के लिए:

    स्केला>: पेस्ट

    [कॉपी/पेस्ट]

    [ctrl + D]

संपादित करें: Antoras उल्लेख के रूप में यह एक संकलक बग होना चाहिए, हो सकता है स्केला संस्करण उपयोगी हो सकता है: स्कैला 2.9.0.1 (एक त्वरित परीक्षण के बाद, अभी भी स्कैला 2.9.1 आरसी 2 में)

उत्तर

2

यह एक कंपाइलर बग प्रतीत होता है। मैंने कंपाइलर एएसटी के आउटपुट का विश्लेषण किया है (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