tra...">

Family polymorphism + myxins?

I have a FAMILY of types that I want to modularly "enrich" with mixins. For example:

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

      

However, the above doesn't work (Scala 2.9.1). The last expression will not compile ( pet.toSimpleString

).

It's just a random strategy that I chose from several attempts: self-typing, abstract types, super [...], etc.

I want to be able to do something like this in the end:

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

      

Where each mixin adds a set of interacting methods to one or more types within the family.

This is the usual pattern I've seen tackling with implicit wrappers based on visitor patterns, etc. But since this is just a recursive application of a regular mixin pattern, I'm wondering if there might be an easier way to achieve it.

+3


source to share


1 answer


Expected error in your case, as Dog

and Person

in mixins do not override Dog

and Person

in Family

, so that self.Person

still belongs to Family.Person

.

This may be closer to what you want

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

      



But then you have something like yucky like

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

      

+5


source







All Articles