#2216 Mixin Inheritance Order

SlimerDude Thu 5 Dec 2013

Given:

mixin A {
    virtual Void eh() {
        echo("A")
    }
}

mixin B : A {
    override Void eh() {
        echo("B")
    }
}

class Example : B, A {
    Void main() {
        eh
    }
}

As A <- B <- Example and B.eh() overrides A.eh() you'd expect Example.main() to print B. Lets see...

A

Woah! Hmmm... If we switch round the inheritance order so B is now last, we get a different result:

class Example : A, B { ... }

Now it prints B!

I know you wouldn't usually list all the inherited classes on the sub class, but still, this looks like a serious bug to me, no?

SlimerDude Sat 28 Dec 2013

Hmm... I still think this is a serious flaw...

brian Sat 28 Dec 2013

Promoted to ticket #2216 and assigned to brian

I think it just that we probably shouldn't let you inherit from both a class and its superclass at the same time

SlimerDude Sat 28 Dec 2013

we probably shouldn't let you inherit from both a class and its superclass at the same time

Um, I don't like that approach. There's no real reason to make redundant inheritance an error condition.

And often, like when you're using frameworks, the super / base classes are outside of your control. If their inheritance changes, that shouldn't automatically break your code.

A contrived example would be if you used a marker mixin on your subclasses, say MySerializable. If the framework then added MySerializable to its base classes, then suddenly all your subclasses stop compiling - not nice! :(

If Fantom could ignore / warn about redundant / duplicate inheritance, that would be much nicer. :)

(As you would already have to check class inheritance stack to raise the error, could you not just remove duplicates from the stack?)

KevinKelley Sat 28 Dec 2013

I think Brian's right, that has to be an error, at least for this example where you're inheriting both base and derived from the same class. There's nothing obvious about which one should apply. By order-of-declaration, but should the later one replace the earlier one, or should the first-match be taken?

It's too easy to get too many concepts conflated into the single hierarchy. Another point is that your Example is really class Example: Obj, A, B, and now it's clearer that you're trying to say that an Example is both a A with virtual eh() and a B with override eh(); which surely doesn't make sense.

If you had Ex1: A and Ex2: Ex1, B, then the redundancy probably makes more sense. And (without checking) I think that would compile. Also if you implement Example::eh() and call either A::eh() or B::eh() you're probably good as well.

A declaration of inheritance is a promise to abide by a protocol: if the library changes the protocol (by adding MySerializable), then you'd probably need to re-evaluate whether your derivation still makes sense... So, I'm not seeing why this shouldn't be a compiler error.

SlimerDude Sat 28 Dec 2013

I guess it depends on whether class Example: A, B {...} specifies direct inheritance, or whether it says Example must descend from both A and B at some point in the inheritance hierarchy.

If direct, then yeah, an error is more appropriate. My take on inheritance comes from the Java world where declaration is more lenient and means the latter.

Login or Signup to reply.