§1.5 Team and role nesting

Multi-level nesting of classes is restricted only by the following rules.

Example code (Nesting):
1
public team class SuperOuter {
2
  public team class RoleAndTeam {
3
    protected class InnerRole {
4
      Runnable foo() { return null; }
5
    }
6
  }
7
  public team class RoleAndTeamSub extends RoleAndTeam {
8
    protected class InnerRole {
9
      Runnable foo() { throw new RuntimeException(); }
10
    }
11
  }
12
}
13
public team class OuterTeam extends SuperOuter {
14
  public team class RoleAndTeam {
15
    protected class InnerRole {
16
      Runnable foo() {
17
        class Local {};
18
        return new Runnable() { // anonymous class definition
19
          public void run() {}
20
        };
21
      }
22
      // class IllegalMember {}
23
    }
24
  }
25
  public team class RoleAndTeamSub {
26
    protected class InnerRole {
27
      Runnable foo() {
28
        RoleAndTeamSub.tsuper.foo();
29
        return OuterTeam.tsuper.foo();
30
      };
31
    }
32
  }
33
}

(a) Nested teams

If a role class is also marked using the team modifier, it may contain roles at the next level of nesting.

  • In the above example (Listing 1.5) class RoleAndTeam starting in line 14 is a role of OuterTeam and at the same time a team containing a further role InnerRole

Such a hybrid role-and-team has all properties of both kinds of classes.

(b) Nested classes of roles

A regular role class (ie., not marked as team, see above) may contain local types (see JLS §14.3 - in the example: class Local), anonymous types (JLS §15.9.5 - in the example: class defined in lines 18-20) but no member types (JLS §8.5 - in the example: illegal class IllegalMember).
The effect is, that nested types of a regular role cannot be used outside the scope of their enclosing role.

(c) Prohibition of cycles

A nested team may not extend its own enclosing team.

(d) Prohibition of name clashes

A nested team may inherit roles from multiple sources: its explicit super team and any of its implicit super classes (roles) from different levels of nesting. If from different sources a team inherits two or more roles of the same name that are not related by implicit inheritance, this is an illegal name clash.

(e) Precedence among different supers

If a role inherits the same feature from several super roles (super and tsuper), an implicitly inherited version always overrides any explicitly inherited feature, i.e., a role with the same simple name is closer related than one with a different name.

Also implicit inheritance alone may produce several candidate methods inherited by a role class. This is a result of team-nesting where each level of nesting may add one more tsuper role if outer teams also participate in an inheritance relationship. In this case a role inherited from an implicit super team of the enclosing team is closer related than a role inherited from an explicit super team. If necessary this rule is applied inside out until a nesting level is found where indeed explicit team inheritance is involved.
So when comparing classes by their fully qualified names the longest common suffix will determine the closest relationship. E.g., SuperOuter.RoleAndTeamSub.InnerRole is the closest ancestor of SubOuter.RoleAndTeamSub.InnerRole because both share the name suffix RoleAndTeamSub.InnerRole.

In the above example (Listing 1.5) role OuterTeam.RoleAndTeamSub.InnerRole has two direct tsuper roles: OuterTeam.RoleAndTeam.InnerRole and SuperOuter.RoleAndTeamSub.InnerRole. Without the method foo defined in lines 27-30, the enclosing class OuterTeam.RoleAndTeamSub.InnerRole would inherit the method foo defined in SuperOuter.RoleAndTeamSub.InnerRole (line 9), because the common name suffix RoleAndTeamSub.InnerRole creates a stronger relationship making that class the closest ancestor.

Example diagram team nesting

(f) Qualified tsuper

A role in a nested team may qualify the keyword tsuper (see §1.3.1.(f) above) by a type name in order to select among different implicit super classes. A term OuterTeam.tsuper evaluates to a corresponding implicit super class within the context of the explicit super-class (here: SuperOuter) of the enclosing team "OuterTeam". A method call OuterTeam.tsuper.m() evaluates to the method version within SuperOuter that best corresponds to the current method containing the tsuper-call.

  • In the above example (Listing 1.5) line 28 selects the method version within the superclass of RoleAndTeamSub (i.e., within RoleAndTeam), resolving to OuterTeam.RoleAndTeam.InnerRole.foo().
  • Line 29 selects a corresponding method from the context of SuperOuter resolving to SuperOuter.RoleAndTeamSub.InnerRole.foo() which has the same semantics as an unqualified tsuper call would have.