2012-11-11 14 views
5

मैं स्काला के नया हूँ और पता है क्यों मैं (मेरे लिए unintuitive) एक क्या करना है निम्न लिखें कोड में पथ निर्भर प्रकार से संबंधित डाली नहीं है। (मैं ही टिककर खेल, setters और न ही nulls पसंद नहीं है, वे अलग संचालन करने के लिए यहाँ हैं और त्रुटियों के स्रोत को स्पष्ट)पथ निर्भर प्रकारों के साथ काम करने वाले भयानक प्रकार से कैसे बचें?

// Module A public API 
class ModA { 
    trait A 
} 

// Module B public API that depends on types defined in Module A 
class ModB(val modA: ModA) { 
    trait B { 
    def getA: modA.A; 
    def setA(anA: modA.A); 
    } 
} 

// One implementation of Module A 
class ModAImpl extends ModA { 
    class AImpl extends A 
} 

// One implementation of Module B 
class ModBImpl(mod: ModA) extends ModB(mod) { 
    class BImpl extends B { 
    private[this] var privA: modA.A = _; 
    override def getA = privA; 
    override def setA(anA: modA.A) = privA = anA; 
    } 
} 

object Main { 
    def main(args: Array[String]): Unit = { 
    // wiring the modules 
    val modAImpl = new ModAImpl; 
    val modBImpl = new ModBImpl(modAImpl); 

    // wiring objects 
    val a = new modAImpl.AImpl; 
    val b = new modBImpl.BImpl; 
    b.setA(a); //don't compile and complain: type mismatch; found: modAImpl.A required: modBImpl.modA.A 

    //i have to do this horrible and coutnerintuitive cast to workaround it 
    b.setA(a.asInstanceOf[modBImpl.modA.A]); 

    var someA: modAImpl.A = null; 
    someA = b.getA; // don't compile with same reason 
    someA = b.getA.asInstanceOf[modAImpl.A]; // horrible cast to workaround 

    println(a == b.getA); // however this prints true 
    println(a eq b.getA); // this prints true too 
    } 
} 

मैं संकलक को सूचित करने की दो प्रकार के होते ही हैं सिंगलटन प्रकारों के बारे में पढ़ा है, लेकिन मुझे नहीं पता कि इसे यहां कैसे लागू करें। अग्रिम धन्यवाद।

उत्तर

5

आप ModB प्रकार पर एक प्रकार पैरामीटर छड़ी कर सकते हैं:

class ModA { trait A } 

class ModB[AA](val modA: ModA { type A = AA }) { 
    trait B { 
    def getA: AA 
    def setA(anA: AA) 
    } 
} 

class ModAImpl extends ModA { class AImpl extends A } 

class ModBImpl[AA](
    mod: ModA { type A = AA }) extends ModB(mod) { 
    class BImpl extends B { 
    private[this] var privA: AA = _ 
    override def getA = privA 
    override def setA(anA: AA) = privA = anA 
    } 
} 

और प्रकार निष्कर्ष सभी वांछित के रूप में बाहर काम करता है:

scala> val modAImpl = new ModAImpl 
modAImpl: ModAImpl = [email protected] 

scala> val modBImpl = new ModBImpl(modAImpl) 
modBImpl: ModBImpl[modAImpl.A] = [email protected] 

scala> val a = new modAImpl.AImpl 
a: modAImpl.AImpl = [email protected] 

scala> val b = new modBImpl.BImpl 
b: modBImpl.BImpl = [email protected] 

scala> b.setA(a) 
+0

बहुत धन्यवाद ट्रैविस जवाब देने के लिए है, लेकिन अपने समाधान केवल अंदर काम करता है वर्ग के दायरे में, एक विधि के दायरे के अंदर (जैसे उदाहरण मैंने मूल रूप से उजागर किया था) यह काम नहीं करता है। लाइन: 'वैल modBImpl = नए ModBImpl (modAImpl)' है कि पहले संकलन, अब के साथ शिकायत: प्रकार मेल नहीं खाता; पाया: ModAImpl आवश्यक: M forSome {प्रकार एम <: मोडा {प्रकार एक = this.A}} और लाइन 'b.set (क)' अब साथ शिकायत: प्रकार मेल नहीं खाता; पाया: modAImpl.A आवश्यक: this.A –

+0

आप उस मामले में स्पष्ट रूप से प्रकार पैरामीटर प्रदान कर सकते हैं ('वैल modBImpl = नए ModBImpl [modAImpl.A] (modAImpl)')। जो संतोषजनक नहीं है, लेकिन यह काम करता है, और यह कास्टिंग से बेहतर है। –

+0

क्षमा करें ट्रैविस, लेकिन आपके द्वारा अभी लिखा गया कोड की रेखा संकलित नहीं है। उस के बावजूद, कि विशेषता मोडा सदस्यों में से बहुत से ग्रहण करें, न सिर्फ ए मैं सभी मोडा के सदस्यों ModB पर उपलब्ध की जरूरत है। –