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.
source to share
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
}
source to share