2013-04-30 10 views
5

क्या कोई स्पष्टीकरण दे सकता है कि निम्न कोड MatchError का कारण क्यों बनता है? इस मामले में MatchError का क्या अर्थ है?ओवरराइडिंग कंपैनियन ऑब्जेक्ट वैल्यूज और स्कैला मैचइरर

class A { 
    def g = A.f 
} 

object A { 
    val f = "Object A" 
} 


class B extends A { 
    override val A.f = "Object B" 
} 

val b = new B 
b.g 

यह काम नहीं करता को देखते हुए, वहाँ एक साथी वस्तु वैल या डीईएफ़ इस के समान ओवरराइड करने के लिए एक तरीका है?

उत्तर

3

सबसे पहले, आप MatchError क्यों देख रहे हैं। किसी ऑब्जेक्ट (एएफ) पर एक मान को स्थिर पहचानकर्ता माना जाता है (जैसा कि स्कैला संदर्भ कहता है, "स्थिर सदस्य [...] ऑब्जेक्ट डिफिशन द्वारा प्रस्तुत किए गए सदस्य या गैर-अस्थिर प्रकारों की मान परिभाषाओं द्वारा)"।

object A extends scala.AnyRef { 
    ... 
    private[this] val f: String = "Object A"; 
    <stable> <accessor> def f: String = A.this.f 
} 

जब एक काम में इस्तेमाल किया, संकलक पैटर्न मिलान में "desugars" इस स्थिर पहचानकर्ता का काम (यह स्थिर किया जा रहा है एक आवश्यक शर्त है):

यहाँ की तरह क्या टाइपकर्ता उत्पादन लग रहा है

<synthetic> private[this] val x$1: Unit = ("Object B": String("Object B") @unchecked) match { 
    case A.f =>() 
} 

यह "ऑब्जेक्ट ए" पैटर्न के खिलाफ "ऑब्जेक्ट बी" से मेल नहीं खाता है, इसलिए यह MatchError फेंकता है।

अपने बड़े प्रश्न के लिए: आप किसी साथी ऑब्जेक्ट पर मूल्यों और विधियों को ओवरराइड नहीं कर सकते/नहीं करना चाहिए। पॉलिमॉर्फिज्म कक्षाओं और उनके उदाहरणों पर लागू होता है, न कि स्थैतिक तरीकों या मूल्यों के लिए। आपके प्रोग्राम के बारे में सोचने का शायद एक बेहतर तरीका है जिसमें किसी साथी ऑब्जेक्ट पर vals/defs को ओवरराइड करना शामिल नहीं है।

+0

धन्यवाद! मैं आम तौर पर साथी वस्तुओं को ओवरराइड करने की आवश्यकता पर सहमत हूं, लेकिन कारण यह है कि मैं इसे यहां करना चाहता हूं परीक्षण उद्देश्यों के लिए, जहां मैं किसी अन्य विधि के साथ साथी ऑब्जेक्ट के अंदर एक विधि को प्रतिस्थापित करना चाहता हूं। इसके अलावा, कुछ भाषाएं स्थिर तरीकों को ओवरराइड करने की अनुमति देती हैं। – deepkimo

1

यह दिलचस्प है! आप एक फ़ाइल में वर्ग परिभाषाओं रख दिया और scalac -print test.scala का उपयोग कर इसे संकलित यदि आप कुछ इस तरह देखेंगे,

[[syntax trees at end of     cleanup]] // scala 
package <empty> { 
    class A extends Object { 
    def g(): String = A.f(); 
    def <init>(): A = { 
     A.super.<init>(); 
    () 
    } 
    }; 
    object A extends Object { 
    private[this] val f: String = _; 
    <stable> <accessor> def f(): String = A.this.f; 
    def <init>(): A.type = { 
     A.super.<init>(); 
     A.this.f = "Object A"; 
    () 
    } 
    }; 
    class B extends A { 
    <synthetic> private[this] val x$1: runtime.BoxedUnit = _; 
    def <init>(): B = { 
     B.super.<init>(); 
     B.this.x$1 = { 
     case <synthetic> val x1: String = ("Object B": String("Object B")); 
     case5(){ 
      if (A.f().==(x1)) 
      { 
       val x2: String = x1; 
       matchEnd4(scala.runtime.BoxedUnit.UNIT) 
      } 
      else 
      case6() 
     }; 
     case6(){ 
      matchEnd4(throw new MatchError(x1)) 
     }; 
     matchEnd4(x: runtime.BoxedUnit){ 
      scala.runtime.BoxedUnit.UNIT 
     } 
     }; 
    () 
    } 
    } 
} 

यह दिखाता है कि संकलक एक आरंभीकरण कि एक मैच है कि मूल्य को देखने के लिए जाँच करता है के साथ एक कक्षा B बनाता है आपने val A.f को ओवरराइड करने में उपयोग किया है मूल मान if (A.f().==(x1)) के बराबर है। ऐसा लगता है कि यह बहुत उपयोगी नहीं है? यदि वे बराबर नहीं हैं तो यह case6() पर कॉल करके मिलान त्रुटि को फेंक देता है। हम class B से override val A.f = "Object A" की परिभाषा को बदलकर इसकी पुष्टि कर सकते हैं।

class B extends A { 
     override val A.f = "Object A" 
} 

scala> val b = new B 
b: B = [email protected] 

तो इसे कैसे ठीक करें? तुम सिर्फ स्पष्टीकरण के लिए ऐसा कर सकते हैं,

class B extends A { 
     override def g = "Object B" 
} 
scala> val b = new B 
b: B = [email protected] 

scala> b.g 
res1: String = Object B 

या

class B extends A { 
     val f = "Object B" 
} 
scala> val b = new B 
b: B = [email protected] 

scala> b.f 
res0: String = Object B 
+0

आप लक्षणों का उपयोग करने पर विचार कर सकते हैं: http://stackoverflow.com/a/7625150/1274818 – tysonjh

+0

आपके फ़िक्स इस सरल कोड उदाहरण के आसपास जाने का एक शानदार तरीका है, लेकिन मैं वास्तव में क्या देख रहा हूं, क्योंकि मैं इसे कॉल करना चाहता हूं मूल अफ विधि। – deepkimo

+0

हां, गुण इस संरचना के लिए एक अच्छा तरीका हैं, लेकिन मेरे मामले में मैं कोड का परीक्षण करना चाहता हूं जो मुख्य कोड को बदले बिना पहले से मौजूद है। – deepkimo

संबंधित मुद्दे