next up previous
Next: Ad-hoc Polymorphism in AspectJ Up: Aspects and Polymorphism in Previous: Aspects and Polymorphism in


Introduction

There are two important points of view on inclusion or subtype polymorphism in object-oriented programs, namely polymorphic access and dynamic dispatch ( Figure Polymorphism).

Figure: Polymorphism
In short, inclusion polymorphism is characterized by invariance in an ``early'' phase (e.g., a call site contains one particular message send foo; or an object contains a known set of features), and by dynamic variance in a ``late'' phase (e.g., considering all the possible implementations of foo for that call site; or all the possible additional features of ). Late binding of methods provides the flexibility of executing different behaviors at the same call site, while preserving the safety of always executing a behavior that is appropriate for the actual receiver object. For object access, we get the flexibility of being able to add new features, and the safety guarantee that known features will indeed be present dynamically. In this paper, we seek a similar kind of safe flexibility by means of polymorphism in connection with aspects.

Inclusion polymorphism is a kind of universal polymorphism, which means that the set of possible forms in the late phase is open-ended [7]. In contrast, in ad-hoc polymorphism, the set of possible forms is determined in the early phase, and one specific form is selected. For example, an overloaded operation also simultaneously denotes more than one function [17]. However, unlike dynamic dispatch, overloading is resolved at compile time and hence is a form of ad-hoc polymorphism.

In AspectJ [22,20], object-oriented polymorphism is supported in the sense that the Java [3] programming language supports polymorphism, and AspectJ is a superset of Java. Similar connections would typically exist with other AOSD approaches. The support for polymorphism in connection with aspects is essentially ad-hoc.

For example, one can write a single implementation of an aspect, which displays polymorphic behavior in different join points. Consider the abstract aspect SimpleTracingin Listing SimpleTracing.java. [*]

(Listing SimpleTracing.java)

package aspect;
import org.aspectj.lang.JoinPoint;
abstract aspect SimpleTracing {
  abstract pointcut tracePoints();
  before(): !within(aspect..*) && tracePoints() {
    trace(thisJoinPoint);
  }
  protected abstract void trace(JoinPoint jp);
}
The thisJoinPoint pseudo variable (and the related pseudo variable thisJoinPointStaticPart) is bound to an object representing the current join point, thus providing access to dynamic (respectively static) information about that join point. This object can be queried with methods such as
  thisJoinPoint.getThis()
or
  thisJoinPointStaticPart.getSignature()
    .getDeclaringType().getName()
which will give different outcomes depending on the actual join point. This is because the pointcut (and hence the aspect) is abstract, which means that an actual aspect using the given before-advice would be a subaspect of SimpleTracing in which the pointcut tracePoints has been made concrete, and the method tracehas been implemented. Hence, an execution of the before-advice would happen in context of an aspect instance whose type is only known by an upper bound, and thisJoinPoint is only known to be a join point.

Moreover, an aspect can define abstract or concrete methods for subaspects to redefine or use, e.g.,

(Listing ExecutingObjectTracing.java)

abstract aspect ExecutingObjectTracing 
  extends SimpleTracing {
  protected void trace(JoinPoint jp) {
    System.out.println("Executing object: " 
      + jp.getThis());
  }
}

Finally, an advice and a pointcut may take arguments such as the receiver object, e.g.,

  after(Point p, int nval): target(p) 
    && args(nval) 
    && call(void Point.setX(int)) {
    System.out.println("x in " + p 
      + " is now set to " + nval + ".");
  }
and this means that the advice code will polymorphically access the receiver, p, of the intercepted invocation of setX.

However, all these examples of polymorphism are ``inherited'' from the base language. Imagine a base language without polymorphism, and they would all evaporate.

Even the notion of an abstract pointcut and associated definitions of concrete pointcuts is not truly polymorphic in the same sense as object-oriented methods. It is true that advice code such as the invocation of tracein Listing SimpleTracing.java is executed depending on a pointcut whose concrete definition is not known in SimpleTracing. In other words, it is not known in SimpleTracing when this advice code will be executed. But for each location in the program where this advice may actually be enabled, it will be considered in context of a concrete subaspect of SimpleTracing for which tracePoints can be checked statically--e.g.,

(Listing PointTracing.java)

aspect PointTracing 
  extends ExecutingObjectTracing {
  pointcut tracePoints():
    execution(* Point+.setX(..));
}
--``is this an invocation of C.setX where C is Point or a subclass thereof?'' Note that even with dynamic pointcuts, e.g., cflow, it is known statically that it is a cflow pointcut, with a known specification, and the dynamic part is only determining whether a given expression is true or not.


next up previous
Next: Ad-hoc Polymorphism in AspectJ Up: Aspects and Polymorphism in Previous: Aspects and Polymorphism in
David H. Lorenz 2003-01-15