I think that you're probably right and that super.m() should be allowed to access concrete methods in interfaces. However, I don't think that we should add this functionality until after AspectJ-1.0. Multiple-inheritance is a well-known quagmire of complexity in OO language design, and is something that should be approached carefully. I'd like to have some calm time to think carefully about any proposal that would expand the power (and the complexity) of AspectJ's current very limited and simple form of multiple-inheritance. As an example of increasing complexity, if we provide the power you suggest here, I can easily see people asking for qualified super calls to disambiguate multiply inherited methods of the same name, something like "ColorMixin.super.getColor()".
Fortunately, your proposal for increasing the power of super can be added to AspectJ-1.1 or some other future version in a mostly backwards compatible way. Therefore, my recommendation is that we mostly table this discussion until after AspectJ-1.0.0 is released.
The part that I'd like to talk about today is the mostly-backwards compatible issue. In order to be able to add this proposal in a completely backwards compatible way to a future version of AspectJ, there is one situation that we are not treating as an error that we should be treating so. I believe that the following (currently legal in AspectJ-1.0beta1) program should be illegal in AspectJ-1.0:
public void m() { ... }
public void I.m() { ... }
This change to AspectJ-1.0 would give us the most room to design a clean solution for super and multiple-inheritance at some future time. It might break some existing AspectJ-1.0beta1 programs; however, I don't believe the odds of that are very high. If you have existing code or designs that this would break, please let me know.
Jim,
Thanks for replying.
I think by simply allowing interfaces to have introduced-implemented
-methods, the whole problem of multiple-inheritance is already
opened.
I have two particular problems:
The first one is a practical one. The other is somewhat academic
(assuming it is not common for a class to implemente multiple
interface with a method of exacly same signature), although important
to consider for the final solution.
1. The situation I was trying to use will not be possible
(or atleast elegantly possible) unless super.method()
problem is fixed.
I have an interface and a default implementation (implemented as
BODY aspect) of it. In most cases, default is fine. There are,
however, a few cases where I need to augment the behavior.
Unless I can call super.method(), such augmentation is not possible.
2. You are right. My next question was going to be about
possibility of "ColorMixin.super.getColor()" :-)
Consider for example,
public interface A {
public void foo();
static aspect BODY {
public void foo() {
System.out.println("A.foo()");
}
}
}
public interface B {
public void foo();
static aspect BODY {
public void foo() {
System.out.println("B.foo()");
}
}
}
public class AB implements A, B {
// No foo() implemented here
}
Current AspectJ implementation chooses to not introduce foo() in
AB at all. Which is fine, considering that it would not be possible
to determine how foo's implemetation should be implemented.
However, I would expect AspectJ to allow adding foo() and let user
choose which implementations to inherit and in what order.
Something like:
public void foo() {
A.super.foo();
// some more code
B.super.foo();
}
Thanks and regards.
-Ramnivas
== Gregor Kiczales' reponse ==
Aargh! our goal was to stear clear of as many of the hard multiple
inheritance (MI) issues as possible. Here's a way of thinking about
the language design that I _think_ can help guide us here.
Our theory about introduction of public methods is that:
- its a rare
- it should probably only be done when introducing an
implementation for a well-known interface
In addition, remember that in our language we have advice.
it seems like we can drive our answer to this issue off of
these combined facts, and that the answer, at least for now, is
that we do not support the full case of _multiple_ inheritance.
We support a weaker thing, which allows a class to get orthogonal
sets of methods from classes and interfaces.
I'm less sure about whether we support overiding of methods inherited
from an interface.
So if you someone wants to do the additive multiple inheritance thing
they can use around/before/after. That means we have less need for the
full power of MI.
I think what I'm saying is that:
- we should signal an error in this case:
> >
> > class SuperC {
> > public void m() { ... }
> > }
> >
> > interface I {
> > aspect BODY {
> > public void I.m() { ... }
> > }
> > }
> >
> > class SubC extends SuperC implements I {
> > public void m() {
> > super.m(); //ERROR: ambiguous reference to either I.m() or
> > SuperC.m()
> > }
> > }
- and we could allow super.method() to work in the simple case,
but we could also prohibit it, at least for now, and point
people to around.
Ramnivas, how does this rationale and set of proposed design decisions
fit for you. Can you use advice the way I mention to get the MI effect
you need?.
== end responses ==