Skip to main content

Notice: This Wiki is now read only and edits are no longer possible. Please see: for the plan.

Jump to: navigation, search



A role class should only apply to explicitly registered base objects.


Normally, a role class virtually adapts all instance of their base class. As a result, any callin binding OTJLD §4 within the role class is triggered on each base instance executing the method bound by the callin. If the effect of the role class should, however, be constrained to specific base objects, a technique is needed for registering some objects while excluding all others.


This pattern only requires three classes, Role and Base, bound by a playedBy declaration, plus of course an enclosing team Registry.


  • Role: The role class excludes all base instances from firing callins using a simple guard predicate (OTJLD §5.4).
  • Registry: The enclosing team offers a registration method with declared lifting (OTJLD §2.3.2) which may even have an empty body.
  • Client: The client, who knows for which base instances callins should fire, registers these base instances using the team's registration method.
public team class Registry {
   protected class Role playedBy Base 
      base when (Registry.this.hasRole(base, Role.class)) 
      // role declarations including callins:
      roleMethod <- before baseMethod;
   public void registerBase(Base as Role object) {
      // no statements required
// Client code:
Registry reg= new Registry();
Base b= new Base();
// some time later:
b.baseMethod(); // callin binding fires
Base b2= new Base();
b2.baseMethod(); // callin binding does not fire, object is not registered
  • A base guard (OTJLD §5.4.2) has to be used in order to actually prevent lifting when evaluating to false.
  • The guard predicate uses the reflective method hasRole (OTJLD §6.1). Passing the class literal Role.class is not strictly required (but might improve performance, as fewer lookups are used internally).


In standard cases these few lines completely suffice. In particular, no hand-coded registry is needed since every team is already a registry for its roles.

If other locations exist (callin or callout bindings) where an instance of Base could be lifted to Role, this will have the effect of implicitly registering that instance, because the guard predicate only applies to the call target of a callin, never to arguments or return values. If this effect is not intended, yet temporarily lifting a Base is required, the reflective method unregisterRole (OTJLD §6.1) might help. However, such situation may indicate that usage of roles is not fully consistent: if a base instance enters a team by lifting as an argument or return value, it is probably relevant for this context and thus it might indeed need to be registered (implicitly or explicitly). In other words, implicit lifting may very well be a part of the required registration protocol.

Related Patterns

  • ObjectRegistration is frequently used in the context of Notification.

Back to the top