§4.3 Base calls

Role methods with a callin modifier should contain a base call which uses the special name base in order to invoke the original base method (original means: before replacement).

(a) Syntax

The syntax for base calls is base.m(), which is in analogy to super calls. A base.m() call must use the same name and signature as the enclosing method. This again follows the rule, that roles should never explicitly use base names, except in binding declarations.

(b) Missing base call

For each callin method, the compiler uses some flow analysis to check whether a base call will be invoked on each path of execution (analysis is very similar to the analysis for definite assignment regarding final variables - JLS §16). The compiler will issue a warning if a base call is missing either on each path (definitely missing) or on some paths (potentially missing). Instead of directly invoking a base call, a callin method may also call its explicit or implicit super version using super.m() or tsuper.m() (see §1.3.1.(f)). In this case the flow analysis will transitively include the called super/tsuper version.

(c) Duplicate base call

If a callin method contains several base calls, the compiler gives a warning if this will result in duplicate base call invocations on all paths (definitely duplicate) or on some paths (potentially duplicate). Again super/tsuper calls are included in the flow analysis (see 4.3(b)).

(d) Parameter tunneling

If a base method has more parameters than a callin method to which it is composed, additional parameters are implicitly passed unchanged from the original call to the base call (original means: before interception). I.e., a call base.m() may invisibly pass additional parameters that were provided by the caller, but are hidden from the role method.

(e) Fragile callin binding

If a role method returns void, but the bound base method declares a non-void result, this is reported as a fragile callin binding: The result can still be provided by the base call, but omitting the base call may cause problems depending on the return type:

  • For reference return types null will be returned in this case.
  • In the case of primitive return types this will cause a ResultNotProvidedException at run-time.

It is an error if a callin method involved in a fragile callin binding has definitely no base call.

(f) Base super calls

If a callin method rm is bound to a base method B1.m that in turn overrides an inherited method B0.m (B0 is a super class of B1), the callin method may use a special form of a base call denoted as

base.super.rm();

Such base super call invokes the super method of the bound base method, here B0.m. This invocation is not affected by any further callin binding.

A base super call bypasses both the original method B1.m and also other callin bindings that would be triggered by a regular base call. For this reason any application of this construct is flagged by a decapsulation warning (see §3.4).

Comment:
Base calls can occur in callin methods that are not yet bound. These methods have no idea of the names of base methods that a sub-role will bind to them. Also multiple base methods may be bound to the same callin method. Hence the use of the role method's own name and signature. The language implementation translates the method name and signature back to the base method that has originally been invoked.
Example code (Base Call):
1
public class ValidatorRole playedBy Point {
2
  callin void checkCoordinate(int value) {
3
    if (value < 0)
4
      base.checkCoordinate(-value);
5
    else
6
      base.checkCoordinate(value);
7
  }
8
  checkCoordinate <- replace setX, setY;
9
}
Effects:
  • Line 2 defines a callin method which is bound to two methods of the base class Point (see line 8).
  • The value passed to either setX or setY is checked if it is positive (line 3).
  • Lines 4 and 6 show calls of the original method (base calls). While line 6 passes the original value, in the negative case (line 4) the passed value is made positive.