AspectJ lets us declare pointcuts within
aspects, classes and interfaces. To create 'library' pointcuts I need to
be able to declare pointcuts in an interface (and let users of the library
program to the interface), and then have implementers of the interface
provide concrete implementations of those pointcuts. Exploring the behaviour
of AspectJ 1.1 I see that we are part of the way there, but not fully.
What I am about to describe is partially bug and partially feature request...
Today I can write:
public interface Foo {
public pointcut bar();
}
This compiles happily, and I can refer
to Foo.bar() in advice (it doesn't match any joinpoints).
If I write
class C implements Foo {}
this does not cause a compilation error
(I believe it should, since C does not define pointcut bar which it's interface
contract says it should).
If I write
class C implements Foo {
public pointcut bar() : execution(...
...);
}
this compiles happily. Writing advice
against Foo.bar does not match anything, writing advice against C.bar()
matches the execution joinpoints. The desired behaviour is that writing
advice against Foo.bar should match against the C definition.
If I write
aspect A implements Foo {}
this does not cause a compilation error
(I believe it should, since C does not define pointcut bar()).
If I change the interface definition
to
public interface Foo {
public abstract pointcut bar();
}
then compilation of A fails with "inherited
abstract pointcut Foo.bar() is not made concrete in A" (good, but
tells me that the pointcut is not being implicitly made abstract when defined
in an interface). Compilation of the empty C declaration still does not
produce the compilation error.
How I think I would like this to behave
is that pointcuts declared in interfaces are implicitly abstract (just
like method definitions in interfaces). If a class or aspect declares that
it implements the interface without providing a concrete definition of
the pointcut then this is a compilation error. Clients should be
able to write advice against the interface, and the advice will apply to
joinpoints matching any of the concrete implementations of interface
in the system (same rules as for abstract / concrete aspect pairs).
Why this is important:
* I can create a standard interface
that clients program to
* Multiple parties can implement the
interface to provide concrete implementations that make sense within their
system. These can even be binary so that implementation details are never
exposed to clients.