2010-10-07 79 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