2012-11-11 75 views
5

我是新來的斯卡拉,不知道爲什麼我必須做一個(直覺對我來說)在下面的代碼中與路徑依賴類型相關的類型轉換。 (我不喜歡的getter,setter方法也沒有空,他們來這裏是爲了獨立的操作和歧義錯誤的根源)如何避免使用路徑依賴類型的可怕類型轉換?

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

非常感謝回答特拉維斯,但你的解決方案僅適用內類範圍,在方法範圍內(就像我最初暴露的例子),它不起作用。 行:'val modBImpl = new ModBImpl(modAImpl);' 以前編譯,現在抱怨:類型不匹配;找到:ModAmpl required:M forSome {type M <:ModA {type A = this.A}} 和行'b.set(a)'現在抱怨:type mismatch;找到:modAImpl.A required:this.A –

+0

在這種情況下('val modBImpl = new ModBImpl [modAImpl.A](modAmpl)'),您可以明確提供類型參數。這不是令人滿意的,但它的工作原理,它比鑄造更好。 –

+0

對不起特拉維斯,但你剛剛寫的代碼行不能編譯。 儘管如此,請假設特質ModA有很多成員,而不僅僅是A.我需要ModB上可用的ModA的所有成員。 –