2011-02-01 21 views
6

मान लें मैं एक आधार वर्ग हैलक्षण और अमूर्त प्रकार

abstract class Base { 

    type B<: Base 

    def rep:String 

    def copy:B 
} 

class MyBase(override val rep:String) extends Base { 
    type B = MyBase 

override def copy = new MyBase(rep) 
} 

मैं तो एक mixin, जिसके लिए मैं वापसी प्रकार चाहते हैं के रूप में एक और विशेषता को जोड़ने के लिए प्रति उचित प्रकार (जिसका अर्थ है बुला कि होने के लिए कोशिश मिक्स्ड पर प्रतिलिपि बी को उचित प्रकार में सेट करके एक मिश्रण प्रकार देता है)। मैं संकलित करने के लिए इसे प्राप्त करने में सक्षम नहीं हूं, या यहां तक ​​कि समझने के लिए कि ओवरराइड कीवर्ड कहां जाना चाहिए।

संपादित: मैं उदाहरण

abstract class Base { 


    type B <: Base 

    def rep:String 

    def copy:B 

} 

class MyBase(val rep:String) extends Base { 

    type B = MyBase 

    def copy = new MyBase(rep) 
} 


trait DecBase extends Base { 

    abstract override def rep = "Rep: "+super.rep 
} 

मेरा प्रश्न है, मैं एक उचित ग्रुप बी कैसे घोषित करने और DecBase के लिए विधि कॉपी, ताकि प्रतिलिपि रिटर्न एक DecBase करते हैं, और भी, क्यों 'जीता परिष्कृत है यह संकलन नहीं है?

println(((new MyBase("ofer") with DecBase)).rep) 

यह (पुनरावर्ती सामान्य प्रकार का उपयोग कर, कुछ गंदगी के साथ) कुछ मैं जावा में हासिल किया जाता है। मुझे यकीन है कि स्कैला में कुछ अच्छा करना संभव है।

संपादित

का उपयोग

trait DecBase extends Base { 

    override type B = DecBase 
    abstract override val rep= "Dec:"+super.rep 
    abstract override def copy = new MyBase(rep) with DecBase 
} 

मैं निम्नलिखित संकलक त्रुटियों

error: overriding type B in class MyBase, which equals com.amadesa.scripts.MyBase; 
type B in trait DecBase, which equals com.amadesa.scripts.DecBase has incompatible type 
println(((new MyBase("ofer") with DecBase)).rep) 

error: overriding type B in class MyBase, which equals com.amadesa.scripts.MyBase; 
type B in trait DecBase, which equals com.amadesa.scripts.DecBase has incompatible type 
abstract override def copy = new MyBase(rep) with DecBase 

उत्तर

2

मैं अपने मिश्रण इस

trait MixIn extends Base { 
    override B = MixinBase 
    override def copy = new MixinBase(rep) 
} 
तरह दिखता में मान मिलता है

मुझे लगता है कि overrideMyBase पर समस्या का हिस्सा है। यह अनावश्यक है और संकलक को भ्रमित करता है।

Base पर वास्तव में एक कार्यान्वयन है, override आवश्यक बनाने के लिए, आपको संकलक को किस विधि का उपयोग करने की आवश्यकता है। यदि यह स्पष्ट नहीं है, तो यह अपने हाथ फेंकता है और एक त्रुटि उठाता है। इसे इस्तेमाल करे।

val b = new MyBase(rep) with MixIn { 
    override def copy = MixIn.super.copy 
} 

MixIn.super.copy आप चाहते हैं कि एक कॉल है।

आप इस पृष्ठ की समीक्षा Scala Class Linearization पर कर सकते हैं यह समझने के लिए कि क्या होता है जब आपके पास किसी प्रकार की विधि के प्रतिस्पर्धात्मक कार्यान्वयन होते हैं।

संपादित करें: ओह यह एक पूरी तरह से अलग समस्या है। यह case MyBase(val rep:String) में वैल है। आप एक वैल के साथ एक वैल ओवरराइड नहीं कर सकते हैं क्योंकि एक वैल अपरिवर्तनीय माना जाता है। आप एक वैल के साथ एक डीफ़ या var ओवरराइड कर सकते हैं, लेकिन दूसरी तरफ नहीं। इसे बनाएं:

trait DecBase extends Base { 
    abstract override val rep = "Rep: "+super.rep 
} 

कृपया अगली बार कंपाइलर त्रुटि शामिल करें। यह समस्या को देखने के लिए यह इतना आसान बनाता है।

+0

मैंने प्रश्न को परिष्कृत किया है। – user44242

+0

फिर से संपादित, इस बार कंपाइलर त्रुटियों को जोड़ा। मेरे लिए महत्वपूर्ण बात कॉपी विधि के लिए सही वापसी प्रकार है। – user44242

+0

अब मुझे इसे काम करने में परेशानी हो रही है। आरंभ करने के लिए, आप बी को बेसबेस होने के लिए ओवरराइड नहीं कर सकते क्योंकि डेकबेस माइबबेस का उप-प्रकार नहीं है। लेकिन इसे ठीक करने के बाद, मुझे अभी भी एक त्रुटि मिल रही है। कंपाइलर ओवरराइडिंग प्रकार बी = माईबेस पसंद नहीं करता है, लेकिन शायद यह कुछ और हो सकता है। – sblundy

0

मुझे लगता है कि यह val rep वर्ग MyBase में किसी भी तरह से जुड़ा हुआ है। def rep लागू करने के लिए आपको MyBase सार परिभाषित करना चाहिए।

abstract class Base { 
    type B <: Base 
    def rep:String 
    def copy: B 
} 

class MyBase(val repVal: String) extends Base { 
    type B = MyBase 
    def rep = repVal 
    def copy = new MyBase(repVal) 
} 


trait DecBase extends Base { 
    abstract override def rep = "Rep: " + super.rep 
} 

println(((new MyBase("ofer"))).rep) // prints: ofer 
println(((new MyBase("ofer") with DecBase)).rep) // prints: Rep: ofer 

आशा इस मदद करता है:

यहां उदाहरण के काम कर रहा है।

val myBase: MyBase = new MyBase("alone") 
val myBaseCopy: MyBase = myBase.copy 

val decBase: DecBase = new MyBase("mixed") with DecBase 
val decBaseCopy: DecBase = decBase.copy 

अपने type घोषणाओं में समानता के बजाय प्रकार सीमा का उपयोग करने के लिए अपने कोड को फिर से लिखने (और यह भी val rep के बीच बेमेल को ठीक करने की सुविधा देता है:

+0

नहीं। स्कैला में, एक डीफ़ या वैल होने के साथ-साथ अदला-बदली होती है। वाल प्रतिनिधि चीज प्रतिनिधि का कार्यान्वयन है। – user44242

+0

क्षमा करें, ऐसा लगता है कि मैं कुछ मौलिक भूल गया :) इंगित करने के लिए धन्यवाद! – tenshi

0

तो के रूप में मैं इसे समझ, लक्ष्य करने के लिए सक्षम होने के लिए है और def rep कुछ अन्य संकलक त्रुटियों छिपा है जो):

abstract class Base { 
    type B <: Base 
    def rep: String 
    def copy: B 
} 

class MyBase(_rep: String) extends Base { 
    type B <: MyBase 
    def rep = _rep 
    def copy = new MyBase(rep) 
} 

trait DecBase extends Base { 
    override type B <: DecBase 
    override abstract def rep = "Rep: " + super.rep 
} 

यह अब कहते हैं कि MyBase.copy एक MyBase या एक उपवर्ग, और DecBase.copy श लौटना चाहिए DecBase या उप-वर्ग वापस लौटाएगा। मुझे विश्वास है कि आप यही चाहते हैं, है ना? अब जिसके परिणामस्वरूप संकलक त्रुटि स्पष्ट है:

temp.scala:10: error: type mismatch; 
found : this.MyBase 
required: MyBase.this.B 
    def copy = new MyBase(rep) 
      ^
one error found 

तो तुम लौट रहे हैं एक MyBase लेकिन तुम सच में उपवर्ग लौटने जा करने के लिए, उदाहरण के लिए की जरूरत है आप के बजाय new MyBase(rep) with DecBase लौटाना चाहते हैं, लेकिन केवल तभी जब आपकी ऑब्जेक्ट new MyBase(...) with DecBase के रूप में घोषित की गई थी। मुझे ऐसा करने का कोई तरीका नहीं पता, हालांकि शायद आप adding a trait after an object has been constructed देख सकते हैं।

+0

संकलित नहीं करता है, भले ही मैं बेस और माईबेस को प्रतिबंधित करता हूं, और DecBase को भूल जाता हूं। कंपाइलर शिकायत करता है: त्रुटि: मिस्चैच टाइप करें; मिला: com.amadesa.scripts.MyBase आवश्यक: MyBase.this.B def copy = new MyBase (rep) – user44242

+1

बिल्कुल। आप 'DecBase.copy' को' डेकबेस 'वापस करने के लिए चाहते हैं, लेकिन यह संभव नहीं है क्योंकि' माईबेस 'वास्तव में ऑब्जेक्ट बना रहा है और' माईबेस 'को' डेकबेस 'के बारे में कुछ नहीं पता है। आप 'डेबबेस' के साथ 'नया माइबबेस (प्रतिनिधि)' को 'नया माइबेस (रेप)' लाइन में बदलने के लिए 'डेकबेस' की अपेक्षा कर रहे हैं। – Steve

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