2012-11-11 23 views
5

Tôi mới sử dụng Scala và không biết tại sao tôi phải thực hiện một loại (không trực quan đối với tôi) kiểu liên quan đến các loại phụ thuộc đường dẫn trong đoạn mã sau. (tôi không thích thu khí, setters cũng không null, họ đang ở đây để hoạt động riêng biệt và disambiguate nguồn gốc của lỗi)Làm thế nào để tránh các loại phôi khủng khiếp làm việc với các kiểu phụ thuộc đường dẫn?

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

Tôi đã đọc về các loại singleton để thông báo cho trình biên dịch khi hai loại là như nhau, nhưng tôi không biết cách áp dụng điều này ở đây. Cảm ơn trước.

Trả lời

5

Bạn có thể dính vào một tham số kiểu trên ModB loại:

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

Và những suy luận kiểu tất cả các hoạt động ra như mong muốn:

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

Rất cảm ơn cho trả lời Travis, nhưng giải pháp của bạn chỉ hoạt động bên trong phạm vi lớp, bên trong một phạm vi phương pháp (như ví dụ tôi đã tiếp xúc ban đầu) nó không hoạt động. dòng: 'val modBImpl = new ModBImpl (modAImpl);' mà trước đây biên dịch, bây giờ phàn nàn với: loại không phù hợp; tìm thấy: ModAImpl bắt buộc: M forSome {type M <: ModA {type A = this.A}} và dòng 'b.set (a)' hiện tuân thủ: loại không phù hợp; tìm thấy: modAImpl.A yêu cầu: this.A –

+0

Bạn có thể cung cấp tham số kiểu một cách rõ ràng trong trường hợp đó ('val modBImpl = new ModBImpl [modAImpl.A] (modAImpl)'). Đó là không thỏa mãn, nhưng nó hoạt động, và nó tốt hơn so với đúc. –

+0

Xin lỗi Travis, nhưng dòng mã bạn vừa viết không biên dịch. Mặc dù vậy, hãy giả sử rằng đặc điểm ModA có rất nhiều thành viên, không chỉ A. Tôi cần tất cả các thành viên của ModA có sẵn trên ModB. –