<< §2.3.1 Implicit role creation | ↑ Table of Contents ↑ | §2.3.3 Smart lifting >> |
§2.3.2 Declared lifting
(a) Parameters with declared lifting
A non-static team-level method or constructor may declare a parameter with two types in order to explicitly denote a place of lifting. Using the syntax
public void m (BaseClass as RoleClass param) { stmts }
a liftable parameter can be declared, provided the second type
(RoleClass
) is a role of (playedBy
) the first type (BaseClass
).
Furthermore, the role type must be a role of the enclosing team class defining the given method.
The role type must be given by its simple (i.e., unqualified) name.
Such a signature requires the caller to provide a base object (here BaseClass
), but
the callee receives a role object (here RoleClass
).
In fact, the client sees a signature in which the "as RoleClass
" part is omitted.
Compatibility between caller and callee sides is achieved by an implicitly inserted lifting translation.
A signature using declared lifting is only valid, if the requested lifting is possible
(see §2.3.3 and §2.3.4 for details).
(b) Super in the context of declared lifting
Calling super
or tsuper
in a method or constructor which
declares lifting for one or more parameters refers to a method or constructor with role type parameters,
i.e., lifting takes place before super invocation. Nevertheless, the super method may also
have a declared lifting signature. It will then see the same role instance(s) as the current method.
(c) Declared lifting of arrays
If a parameter involving explicit lifting should be of an array type, the syntax is
public void m (BaseClass as RoleClass param[]) ...
Here the brackets denoting the array apply to both types, BaseClass
and RoleClass
.
(d) Declared lifting for catch blocks
Also the argument of a catch block may apply declared lifting like in:
catch (BaseException as RoleClass param) { stmts }
This syntax is only valid in a non-static scope of a team (directly or nested).
In the given example, RoleClass
must be played by BaseException
.
Note, that RoleClass
itself need not be a throwable.
As the effect of this declaration the catch block will catch any exception of type BaseException
and provides it wrapped with a RoleClass
instance to the subsequent block.
Also note, that re-throwing the given instance param
has the semantics of implicitly lowering
the role to its base exception before throwing, because the role conforms to the required type
Throwable
only via lowering.
(e) Generic declared lifting
A method with declared lifting may introduce a type parameter that is bounded relative to a given role type. Such bound is declared as:
<AnyBase base SuperRole>
void teamMethod(AnyBase as SuperRole arg) {
// body using arg as of type SuperRole
}
This means that AnyBase
is a type parameter whose instantiations must all be liftable to role SuperRole
.
The given type bound requires the call site to supply an argument that is compatible to any base class
for which the current team contains a bound role that is a sub class of SuperRole
, including SuperRole
itself.
However, SuperRole
itself need not be bound to any base class.
On the other hand, different valid substitutions for AnyBase
need not be related by inheritance.
Note:
This feature supports generalized treatment of otherwise unrelated base classes. This is done by defining one bound role for each base under consideration and by having all these roles extend a common unbound role.Example code (Declared Lifting):
1 | team class Super { |
2 | public class MyRole playedBy MyBase { ... } |
3 | void m (MyRole o) { ... }; |
4 | } |
5 | team class Sub extends Super { |
6 | void m (MyBase as MyRole o) { |
7 | // inside this method o is of type MyRole |
8 | super.m(o); |
9 | } |
10 | } |
11 | Sub s_team = new Sub(); |
12 | MyBase b = new MyBase(); |
13 | s_team.m(b); // clients see a parameter "MyBase o" |
<< §2.3.1 Implicit role creation | ↑ Table of Contents ↑ | §2.3.3 Smart lifting >> |
Effects:
m
with a base instance (typeMyBase
) as its argument (line 13).m
, the argument is lifted such that the method body receives the argument as of typeMyRole
(line 8).