2012-11-11 22 views
5

Scala'da yeniyim ve aşağıdaki kodda yola bağımlı türlerle ilgili neden bir (benim için anlamadığım) tür dökümünü yapmam gerektiğini bilmiyorum. ,Yol bağımlı türlerle çalışan korkunç tipte dökümler nasıl önlenir?

// 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 
    } 
} 

Ben iki tip aynı olduğunda derleyici bilgilendirmek için tekil türleri hakkında okudum (onlar ayrı operasyonlarda için buradayız ve hataların kaynağını belirsizliği, alıcılar, ayarlayıcılar ne de boş değerlere sevmiyorum) ama bunu nasıl uygulayacağımı bilmiyorum. Şimdiden teşekkürler.

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

Ve tür kesmesi tüm istediğiniz gibi çalışır:

cevap

5

Sen ModB türlerinde bir tür parametresi yapışabilir Travis cevaplanması için

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

Çok teşekkür ancak çözüm yalnızca içinde çalışır sınıf kapsamı, bir yöntem kapsamı içinde (aslında maruz kaldığım örnek gibi) işe yaramıyor. satırı: 'val modBImpl = yeni ModBImpl (modAImpl);' daha önce derleme, şimdi ile şikayet: tür uyuşmazlığı; Bulunan: ModAImpl gerekli: M forSome {type M <: ModA {tip A = this.A}} ve 'b.set (a)' satırı şu şekilde davranır: tür uyuşmazlığı; found: modAImpl.A required: this.A –

+0

Bu durumda, açık olarak type parametresini sağlayabilirsiniz ('val modBImpl = new ModBImpl [modAImpl.A] (modAImpl)'). Hangi tatmin edici değil, ama işe yarıyor ve dökümden daha iyidir. –

+0

Üzgünüm Travis, ama yazdığınız kod satırı derlemiyor. Buna rağmen, lütfen ModA'nın sadece A değil çok sayıda üyesi olduğunu varsayalım. ModB'deki tüm ModA üyelerine ihtiyacım var. –