Inter-type declarations are challenging to support using an annotation style. It's very important to preserve the exact same semantics between the code style and the annotation style. We also want to support compilation of a large set of AspectJ applications using a standard Java 5 compiler. For these reasons, in the initial release of AspectJ 5 we will only support inter-type declarations on interfaces using the annotation style.
Consider the following aspect:
public aspect MoodIndicator { public interface Moody {}; private Mood Moody.mood = Mood.HAPPY; public Mood Moody.getMood() { return mood; } declare parents : org.xyz..* implements Moody; before(Moody m) : execution(* *.*(..)) && this(m) { System.out.println("I'm feeling " + m.getMood()); } }
This declares an interface Moody, and then makes two inter-type declarations on the interface - a field that is private to the aspect, and a method that returns the mood. Within the body of the inter-type declared method getMoody, the type of this is Moody (the target type of the inter-type declaration).
Using the annotation style this aspect can be written:
@Aspect public class MoodIndicator { public interface Moody { Mood getMood(); }; @DeclareParents("org.xzy..*") class MoodyImpl implements Moody { private Mood mood = Mood.HAPPY; public Mood getMood() { return mood; } } @Before("execution(* *.*(..)) && this(m)") void feelingMoody(Moody m) { System.out.println("I'm feeling " + m.getMood()); } }
This is very similar to the mixin mechanism supported by AspectWerkz. The effect of the @DeclareParents annotation is equivalent to a declare parents statement that all types matching the type pattern implement the interface implemented by the annotated class. In addition, the member declarations within the annotated class are treated as inter-type declarations on the implemented interface. Note how this scheme operates within the constraints of Java type checking and ensures that this has access to the exact same set of members as in the code style example.
The annotated class may only extend Object, and may only implement a single interface. The interface implemented by the class may itself extend other interfaces.