2010-10-07 69 views
4

更新:澄清和擴大,因爲原來的問題是太遠簡化斯卡拉遞歸仿製藥:父母(孩子)和兒童[家長]

我需要一雙特質,每個指另一方面,父母和孩子的班級必須相互關聯。

trait Parent [C <: Child] { 
    def foo(c: C) 
} 

trait Child [P <: Parent] { 
    def parent: P = ... 
    def bar = parent.foo(this) 
} 

,從而實現類必須成對出現:

class ActualParent extends Parent [ActualChild] { 
    def foo(c: ActualChild) = ... 
} 

class ActualChild extends Child [ActualParent] { 
} 

不幸的是,編譯器不會因爲泛型類型是不完整喜歡這些特質。而不是C <: Child它需要說C <: Child[東西]。使他們不明無法正常工作或:

trait Parent [C <: Child[_]] { 
    def foo(c: C) 
} 

trait Child [P <: Parent[_]] { 
    def parent: P = ... 
    def bar = parent.foo(this) 
} 

現在抱怨的parent.foo(this)行,因爲它不知道this是正確的類型。 parent的類型需要爲Parent[this.type],才能撥打foo以獲得正確的類型。

我在想一定有一種方法來引用一個對象的類型?或者是一個需要它自己的類型?


更新:繼@丹尼爾的回答,我試着用孩子中一個抽象類型成員陳述泛型類型這樣的父類型:

trait Parent [C <: Child] { 
    def foo(c: C) 
} 

trait Child { 
    type P <: Parent[this.type] 

    def parent: P = ... 
    def bar = parent.foo(this) 
} 

這ISN當我嘗試實現它時不工作:

class ActualParent extends Parent [ActualChild] { 
    def foo(c: ActualChild) = ... 
} 

class ActualChild extends Child { 
    type P = ActualParent 
} 

給出以下錯誤:

overriding type Parent in trait Child with bounds >: Nothing <: Parent[ActualChild.this.type] 
type Parent has incompatible type 

這是什麼意思?

回答

5

您可以使用http://programming-scala.labs.oreilly.com/ch13.html給出的方法:

abstract class ParentChildPair { 
    type C <: Child 
    type P <: Parent 

    trait Child {self: C => 
    def parent: P 
    } 

    trait Parent {self: P => 
    def child: C 
    } 
} 

class ActualParentChildPair1 { 
    type C = Child1 
    type P = Parent1 

    class Child1 extends Child {...} 

    class Parent1 extends Parent {...} 
} 
+0

看起來正確。現在你將如何擴展到包含父母 - >孩子 - >孩子的鏈條? – 2010-10-08 07:46:35

+0

這種方法很成功,但我不太滿意。我不確定我能夠充分解釋原因。 – 2010-10-08 16:06:39

1

你可以寫C <: Child[_]

+1

我想這將工作,但我認爲OP是在父母[C Synesso 2010-10-07 23:39:53

+0

正如Synesso所說,Child [_]不會強制讓父母和孩子相互匹配。 – 2010-10-07 23:49:55

+0

你爲什麼要使用泛型?爲什麼不使用參數:class Parent(c:Child); class Child(p:Parent) – sschaef 2010-10-08 00:25:11

3

它可以用抽象類型成員完成。

class Parent { 
    type C <: Child 
    def child: C = null.asInstanceOf[C] 
} 

class Child { 
    type P <: Parent 
    def parent: P = null.asInstanceOf[P] 
} 
+0

這讓我通過編譯器警告,但不強制父類和子類必須與其他類相關的條件。 – 2010-10-08 07:22:23

+0

查看我的答案基於抽象類型成員。 – 2010-10-08 08:10:29

3

繼@丹尼爾的回答,我可以用一個抽象類型成員的孩子中陳述泛型類型這樣的父類:

trait Parent [C <: Child] { 
    def foo(c: C) 
} 

trait Child { 
    type P <: Parent[this.type] 

    def parent: P = ... 
    def bar = parent.foo(this) 
} 

this.type不是仿製藥直接使用,但在參數似乎是罰款。這種方法比周圍的抽象類少得多,並且允許更靈活的用途,例如也是父母的孩子。

1

即使它沒有成功,我會記錄這條道路作爲答案。

使用抽象類型成員,國家界限的回頭參考this.type類型:

trait Parent { 
    type C <: Child { type P <: this.type } 
    def foo(c: C) 
} 

trait Child { 
    type P <: Parent { type C <: this.type } 
    def parent: P 
    def bar = parent.foo(this) 
} 

class ActualParent extends Parent { 
    type C = ActualChild 
    def foo(c: ActualChild) = println("Hello") 
} 

class ActualChild extends Child { 
    type P = ActualParent 
    def parent = new ActualParent 
} 

這裏的問題是,編譯器不與孩子類型父的連接this,因此調用parent.foo(this)結果在:

type mismatch 
found : Child.this.type (with underlying type Child) 
required: _3.C where val _3: Child.this.P