The notion of late binding of advice introduces genuine polymorphism into the aspect part of the language, and it even enables us to achieve the effect of late binding of methods in a base language that does not support late binding of methods. Assume that the base language always select method implementations statically, but supports late binding of advice. Now consider the following definitions: (Advice-can-do-dynamic-dispatch)
aspect addIncrXY {
after incrXY(FigureElement fe, int x, int y):
target(fe)
&& args(x,y)
&& call(void FigureElement.incrXY(int,int)) {
// implementation of incrXY for FigureElement
...
}
after incrXY(Point p, int x, int y):
target(p)
&& args(x,y)
&& call(void Point.incrXY(int x, int y)) {
// implementation of incrXY /**+for+**/ Point
...
}
... // implementations for other subclasses
}
Along with these definitions, we would have an empty incrXYmethod in the FigureElement class (and no other incrXYmethods in any of the subclasses of FigureElement). This empty
method is bound statically, but the support for late binding of advice
ensures that the appropriate behavior for the actual class of the
receiver is invoked after the execution of the empty method. The
effect is the same as it would have been if the base language had
supported late binding of ordinary methods, and we had used them.
This approach is generally applicable, hence late binding of ordinary methods is subsumed by late binding of advice.