It is possible to redefine concrete pointcuts in the subaspect. For example, the abstract aspect ReturnValueTracingin Listing ReturnValueTracing.java,
(Listing ReturnValueTracing.java)
abstract public aspect ReturnValueTracing
extends ExecutingObjectTracing {
pointcut tracePoints(): call(*.new (..));
after() returning (Object o): tracePoints() {
System.out.println("Return: " + o);
}
}
defines a concrete pointcut
tracePoints, which designates constructor calls.
Its after-returning advice assumes the join points are
constructor calls; and the concrete aspect
ConstructorTracing,
(Listing ConstructorTracing1.java)
public aspect ConstructorTracing
extends ReturnValueTracing {}
would trace newly constructed objects.
However, it is an error to put after-returning advice on a join point that
does not return a value or returns a value of an incorrect type.
Had
the concrete aspect ConstructorTracing mistakenly redefined the
pointcut tracePoints to be constructor executions rather than
calls, e.g.,
(Listing ConstructorTracing2.java)
public aspect ConstructorTracing
extends ReturnValueTracing {
pointcut tracePoints(): execution(*.new (..));
}
then there wouldn't have been a return value. Thus,
by overriding a pointcut designator,
a subaspect might
break inherited advice code. Currently in AspectJ, the compiler
will complain that the return value will bind to null, but will ignore
a type mismatch.