Inter-type declarations
Prev | Chapter 2. The AspectJ Language | Next

## Inter-type declarations

Aspects can declare members (fields, methods, and constructors) that are owned by other types. These are called inter-type members. Aspects can also declare that other types implement new interfaces or extend a new class. Here are examples of some such inter-type declarations:

This declares that each `Server` has a `boolean` field named `disabled`, initialized to `false`:

      private boolean Server.disabled = false;

It is declared `private`, which means that it is private to the aspect: only code in the aspect can see the field. And even if `Server` has another private field named `disabled` (declared in `Server` or in another aspect) there won't be a name collision, since no reference to `disabled` will be ambiguous.

This declares that each `Point` has an `int` method named `getX` with no arguments that returns whatever `this.x` is:

      public int Point.getX() { return this.x; }

Inside the body, `this` is the `Point` object currently executing. Because the method is publically declared any code can call it, but if there is some other `Point.getX()` declared there will be a compile-time conflict.

This publically declares a two-argument constructor for `Point`:

      public Point.new(int x, int y) { this.x = x; this.y = y; }

This publicly declares that each `Point` has an `int` field named `x`, initialized to zero:

      public int Point.x = 0;

Because this is publically declared, it is an error if `Point` already has a field named `x` (defined by `Point` or by another aspect).

This declares that the `Point` class implements the `Comparable` interface:

      declare parents: Point implements Comparable;

Of course, this will be an error unless `Point` defines the methods required by `Comparable`.

This declares that the `Point` class extends the `GeometricObject` class.

      declare parents: Point extends GeometricObject;

An aspect can have several inter-type declarations. For example, the following declarations

      public String Point.name;
      public void Point.setName(String name) { this.name = name; }

publicly declare that Point has both a String field `name` and a `void` method `setName(String)` (which refers to the `name` field declared by the aspect).

An inter-type member can only have one target type, but often you may wish to declare the same member on more than one type. This can be done by using an inter-type member in combination with a private interface:

      aspect A {
        private interface HasName {}
        declare parents: (Point || Line || Square) implements HasName;

        private String HasName.name;
        public  String HasName.getName()  { return name; }
      }

This declares a marker interface `HasName`, and also declares that any type that is either `Point`, `Line`, or `Square` implements that interface. It also privately declares that all `HasName` object have a `String` field called `name`, and publically declares that all `HasName` objects have a `String` method `getName()` (which refers to the privately declared `name` field).

As you can see from the above example, an aspect can declare that interfaces have fields and methods, even non-constant fields and methods with bodies.

### Inter-type Scope

AspectJ allows private and package-protected (default) inter-type declarations in addition to public inter-type declarations. Private means private in relation to the aspect, not necessarily the target type. So, if an aspect makes a private inter-type declaration of a field

      private int Foo.x;

Then code in the aspect can refer to `Foo`'s `x` field, but nobody else can. Similarly, if an aspect makes a package-protected introduction,

      int Foo.x;

then everything in the aspect's package (which may or may not be `Foo`'s package) can access `x`.

### Example: `PointAssertions`

The example below consists of one class and one aspect. The aspect privately declares the assertion methods of `Point`, `assertX` and `assertY`. It also guards calls to `setX` and `setY` with calls to these assertion methods. The assertion methods are declared privately because other parts of the program (including the code in `Point`) have no business accessing the assert methods. Only the code inside of the aspect can call those methods.

      class Point  {
          int x, y;

          public void setX(int x) { this.x = x; }
          public void setY(int y) { this.y = y; }

          public static void main(String[] args) {
              Point p = new Point();
              p.setX(3); p.setY(333);
          }
      }

      aspect PointAssertions {

          private boolean Point.assertX(int x) {
              return (x <= 100 && x >= 0);
          }
          private boolean Point.assertY(int y) {
              return (y <= 100 && y >= 0);
          }

          before(Point p, int x): target(p) && args(x) && call(void setX(int)) {
              if (!p.assertX(x)) {
                  System.out.println("Illegal value for x"); return;
              }
          }
          before(Point p, int y): target(p) && args(y) && call(void setY(int)) {
              if (!p.assertY(y)) {
                  System.out.println("Illegal value for y"); return;
              }
          }
      }

Prev | Home | Next
Advice | Up | thisJoinPoint