Latest News

§7 Role Encapsulation

Concepts of encapsulation

Protected roles
A role with visibility protected cannot be externalized, which means its type cannot be used outside the declaring team (§1.2.3).
Confined roles
Confined roles are encapsulated even stricter than protected roles: the compiler will ensure that by no means any object outside the enclosing team will ever have a reference to a confined role.
Opaque roles
Opaque roles build on the guarantees of confined roles but allow to be shared in a limited way such that no information is exposed.

§7.1 Opaque roles↑ §7

The purpose of the two IConfined interfaces (see §6.2.(a)) is to define opaque roles: Any role implementing IConfined can be externalized using this type, such that external clients cannot access any features of the role. The type IConfined exposes no features and references of this type cannot be widened to any type not even to java.lang.Object.
If the actual role type is furthermore invisible outside the team (by not declaring it public), it is perfectly safe to externalize such roles using type IConfined (which is a public interface) and pass them back to the owning team. The encapsulation of the team is in no way breached by externalizing opaque roles, which can only be used as a handle into internal state of the team.

The difference between the two mentioned interfaces is that ITeam.IConfined requires to use this type or any subtype as externalized role. Such a reference contains the information of the enclosing team. Even stricter control can be imposed using the regular interface IConfined. Here not even team membership is visible to clients using a reference of this type.

§7.2 Confined roles↑ §7

Subclassing Team.Confined with a protected class yields a role class to which no object outside the team will ever have a reference. The point here is that instances of a role class with a regular super class can be widened to this super class. Widening can occur either in an assignment or when invoking a method which the role inherits from the regular super class, where the this reference is widened. In both cases the widened reference is no longer protected by the team and can leak out. This would break encapsulation of a role object that should only be accessible within the enclosing team.
Subclasses of Team.Confined are not compatible to any class outside their enclosing team (including java.lang.Object) and do not inherit any methods that have the danger of leaking this.

(a) Inhibition of overriding

The types ITeam.IConfined and Team.Confined cannot be overridden (cf. §1.3.1.(c)).

(b) Arrays of Confined

For any confined type C, i.e., a type which is not compatible to Object, an array of C is not compatible to an array of Object nor to Object itself. This rule ensures that confinement cannot be bypassed by a sequence of compatible assignments and casts.

Upcoming:
Only by widening to a non-role super-type, a role instance can be accessed from outside the team. In the future this can be inhibited by restricted inheritance.
Example code (Role Encapsulation):
1
public team class Company {
2
  private HashMap<String,Employee> employees;
3
  ...
4
  protected class Employee implements IConfined {
5
    void pay(int amount) { ... }
6
    ...
7
  }
8
  public IConfined getEmployee(String ID) {
9
    return employees.get(ID); // implicit widening to IConfined
10
  }
11
  public void payBonus(IConfined emp, int amount) {
12
    ((Employee)emp).pay(amount); // explicit narrowing
13
  }
14
}
15
public class Main {
16
  public static void main(String[] args) {
17
    final Company comp = new Company();
18
    IConfined<@comp> emp = comp.getEmployee("emp1");
19
    // System.out.println(emp); <– forbidden!
20
    comp.payBonus(emp, 100);
21
  }
22
}
Effects:
  • The protected role Employee implements the above described interface IConfined and therefore becomes opaque (line 4).
  • Methods sharing such an opaque role with the outside of the enclosing team have to use the type IConfined (line 8, line 11).
  • It is possible to obtain an instance of such a role by using the type IConfined (line 18).
  • Trying to access any feature of this instance, for example toString(), will cause a compilation error (line 19).
  • Passing the opaque role reference back into the team works well (line 20).
  • Inside the team some conversions between the types IConfined and the intrinsic role type Employee may be necessary (line 9 and 12).