#1229 Mixin inheritance conflict resolution (evolving interfaces)

katox Fri 24 Sep 2010

I ran into a mixin conflict lately and I found out I'm unusure what is the recommended way how to resolve an inheritance mixin conflict.

The situation is quite simple:

mixin A	{ virtual Str myStr() { return "+A" } }
mixin B	{ virtual Str myStr() { return "+B" } }
class C : A, B	{ override Str myStr() { return "C" } }

class Main 
{ static Void main() 
  {
  c := C()
  echo(c.myStr)
  }
}

Mixin B didn't used to contain myStr but it is desirable to have it there now. There is nothing special about C - its myStr result should only contain a combination of return values of myStr in A and B (I can imagine sometimes only A or B variant would suffice).

There are quite a few options but every single one has some limitations. What would you suggest? And what is the best way if myStr isn't virtual?

Sidenote: though the difference between mixins and traits are subtle, don't have traits an edge against mixins in case of evolving interfaces? I haven't found much on this topics on teh internets but this oldschool paper (seems quite good and still valid though).

yachris Fri 24 Sep 2010

"Congratulations, your digging has unearthed a diamond!"

The wiki page referred to above has a good description of the way various languages deal with this problem.

DanielFath Fri 24 Sep 2010

Technically speaking that's a triangle not a diamond.

vkuzkokov Fri 24 Sep 2010

Even more technically: it's "V-problem" since A and B are not connected in any way.

katox Fri 24 Sep 2010

Good to amuse you ;)

Still, this is not groovy or c++ so I have to admit I don't know the syntax how to address methods in A or B without refactoring it all.

brian Fri 24 Sep 2010

In Fantom, the compiler forces you to choose which one you want to use or to create your own version. For example your choices for C.myStr are:

override Str myStr() { return A.super.myStr }  // named super of A
override Str myStr() { return B.super.myStr }  // named super of B
override Str myStr() { return "C" }            // new implementation

In fact, this situation is the primary use case for named supers.

katox Fri 24 Sep 2010

I see, thanks Brian! Couldn't find the named super in docs.

Should've split that and the trait remark into separate topics really.

yachris Fri 24 Sep 2010

That's a nice solution... no wacky compiler rules to memorize, and the implementations are there in a sensible way to reuse. Great!

brian Fri 24 Sep 2010

katox Sat 25 Sep 2010

Yeah, thanks I figured that afterwards. I searched for conflict resolution, mixins, methods and similar. I think this is not the first time I've been unsuccessful with the search (even though the placement is ok). Maybe a link to super would be good from methods and mixins just to play safe...

DanielFath Tue 28 Sep 2010

Speaking of, from what I can tell the biggest difference between mixin and traits is the fact that traits are stackable and mixins aren't. It's kinda cool feature but I doubt I'd see traits in Fantom.

zyhong Tue 28 Sep 2010

I love fantom. But stackable trait is something that I like scala over fantom. I think fantom offer too less while scala offer too much. I guess it is hard to design a language that offer a good balance of feather.

Login or Signup to reply.