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.