Skip to main content

Notice: This Wiki is now read only and edits are no longer possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.

Jump to: navigation, search

OTPattern/BaseclassGeneralization

Intent

Several base classes should be treated uniformly although they share no common superclass (except for java.lang.Object).

Motivation

A team may want to provide a uniform view onto objects of several unrelated base classes. Usually this means, that all bases should participate in a common protocol which may be added using roles.

Applicability

Generally there are no restrictions for using this pattern. However, to get the best results all involved base classes should exhibit some similarity that justifies the generalized view. Still, those similarities may be realized by completely unrelated methods and/or fields.

Structure

OTBaseclassGeneralization.png

Generalization is only realized within the team, using one bound role per unrelated base class plus one unbound role as the common super class of the bound roles.

Any feature expected from the base object is declared using an abstract role method in the unbound role. Thus, each bound role is required to implement the inherited abstract methods, which will usually happen by means of various callout bindings.

Participants

  • SpecificBase[i] : Those unrelated base classes over which should be generalized.
  • TeamComponent: A team enclosing all roles involved. The TeamComponent may also provide unified behavior involving any of the bound base classes.
  • CommonSuperRole: This abstract unbound role declares the common view onto all involved bases.
  • SpecificRole[i] : Each specific role extends the CommonSuperRole and binds to one SpecificBase[i].

Collaborations

The generalized view is achieved by the mentioned callout bindings which map the abstract methods of the unbound super role to methods provided in the various base classes. In these callout bindings names can easily be adjusted. Also parameter mappings are useful for bridging further mismatches between provided (base) and required (role) methods.

When designing the enclosing team as a TeamComponent the uniform view can be exposed by a team level method with parameterized declared lifting (see OTJLD §2.3.2.e and below).

Implementation

While defining the roles is quite straight-forward, the uniform team level method requires special typing to allow for usage with bases of unrelated types:

public team class TeamComponent {
   abstract protected class CommonSuperRole {
      abstract void commonBehavior();
   }
   protected class SpecificRole1 extends CommonSuperRole playedBy SpecificBase1 {
      commonBehavior -> specificBehavior1;
   }
   // ... more specific roles bound to other specific bases ...
 
   /** Generic API for arbitrary bases: */
   public <AnyBase base CommonSuperRole> void handleBase(AnyBase as CommonSuperRole arg) {
      arg.commonBehavior();
   }
}

The method handleBase(..) can then be invoked with an argument of any base class for which a bound role as subclass of CommonSuperRole exists, like in

TeamComponent t = new TeamComponent();
SpecificBase1 b1 = new SpecificBase1(); // or subclass
t.handleBase(b1);

Related Patterns

  • As mentioned above the TeamComponent is likely to follow the same-named pattern TeamComponent

Back to the top