家族多态性+ Mixins?

时间:2013-02-05 09:03:52

标签: scala mixins traits

我有一个类型的家庭,我想用mixins模块化“丰富”。例如:

trait Family {
  self =>
  trait Dog {
    def dogname:String
    def owner:self.Person
  }
  trait Person {
    def name:String
    def pet:self.Dog
  }
}

trait SerializableFamily extends Family {
  trait Dog extends super.Dog {
    def toSimpleString:String = "Dog(" + dogname + ")"
  }
  trait Person extends super.Person {
    def toSimpleString:String = "Person(" + name + ") and his pet " + pet.toSimpleString
  }
}

trait SerializableFamily2 extends Family {
  trait Dog extends super.Dog {
    def toLoudString:String = "Dog(" + dogname.toUpperCase + ")"
  }
  trait Person extends super.Person {
    def toLoudString:String = "Person(" + name.toUpperCase + ") and his pet " + pet.toLoudString
  }
}

但是,上述方法不起作用(Scala 2.9.1)。最后一个表达式无法编译(pet.toSimpleString)。

这只是我从几个尝试过的随机策略:自我打字,抽象类型,超级[...]等。

我希望能够做到这样的事情,最终:

val family = new Family with SerializableFamily with TraversableFamily with FooFamily {}

每个mixin在家庭中的一个或多个类型中添加一组合作方法。

这是我通过使用隐式包装器,基于模式匹配的访问者等解决的常见模式。但由于它只是常规mixin模式的递归应用,我想知道是否可能有更简单的方法来实现它

1 个答案:

答案 0 :(得分:5)

您的情况会出现错误,因为mixins中的DogPerson 覆盖 DogPerson Family 1}},以便self.Person仍然引用Family.Person

这可能更接近你想要的

trait Family {
  // type DogType = Dog won't work because then two different mixins 
  // have incompatible DogType implementations
  type DogType <: Dog
  type PersonType <: Person

  trait Dog {
    def dogname:String
    def owner:PersonType 
  }
  trait Person {
    def name:String
    def pet:DogType 
  }
}

trait SerializableFamily extends Family {
  type DogType <: Dog
  type PersonType <: Person

  trait Dog extends super.Dog {
    def toSimpleString:String = "Dog(" + dogname + ")"
  }
  trait Person extends super.Person {
    def toSimpleString:String = "Person(" + name + ") and his pet " + pet.toSimpleString
  }
}

但是你有一些令人讨厌的东西,比如

new Family with SerializableFamily with TraversableFamily with FooFamily {
  type DogType = super[SerializableFamily].Dog with super[TraversableFamily].Dog with super[FooFamily].Dog
}