A better way is to give names to advice. This is similar to the mechanism commonly used with methods: When a given method implementation is selected during late binding, the set of potential implementations will all have the same name (and, in languages with static overloading, also `sufficiently similar' types of arguments). So we might introduce syntax to give names to advice, and then use it as follows: (Polymorphic-advice-with-name)
aspect IncrTracking { after trackIncr(FigureElement fe): target(fe) && call(void FigureElement.incrXY(int,int)) { System.out.println("IncrTracking: " + "Moving the figure element " + fe); } after trackIncr(Point p): target(p) && call(void Point.incrXY(int,int)) { System.out.println("IncrTracking: " + "Moving the point at (" + p.getX() + "," + p.getY() + ")"); } after(Point p): call(void p.incrXY(int,int) { p.x++; } }Note that the two named advice declarations (named trackIncr) are in the same group, but the third (traditional, unnamed) advice is in a group of its own, and advice declarations with other names than trackIncr are of course also in different groups. With this rule we might have trackIncr advice in one or more aspects having an argument of type FigureElement or a subclass thereof.