<< §3.1 Callout method binding | ↑ Table of Contents ↑ | §3.3 Lifting and lowering >> |
§3.2 Callout parameter mapping
(a) with clause
If the method designators in a callout binding are signatures
(not just method names), parameters and return value may
be mapped by a with{...}
sub-clause. Parameter mappings may only occur if the enclosing role is a class, not an interface.
(b) Mapping one parameter
For each parameter of the provided base method, exactly one parameter mapping defines, which value will actually be passed to the base method. Callout parameter mappings have this form:
expression -> base_method_parameter_name
(c) Result mapping
The return value of a callout method may be provided by a result mapping:
result <- expression
The right hand side expression of a result mapping may use the special identifier
result
to refer to the value returned by the base method.
In a method binding with parameter mappings, it is an error to use
result
as the name of a regular method argument.
Example code (Callout Parameter Mapping):
1 | Integer absoluteValue(Integer integer) -> int abs(int i) with { |
2 | integer.intValue() -> i, |
3 | result <- new Integer(result) |
4 | } |
(d) Visible names
Each identifier that appears within the expressions of a parameter mapping must be either:
- a feature visible in the scope of the role instance.
- a parameter of the role method (for parameter mappings).
- the special name
result
(for result mappings). - in a result mapping also the special name
base
can be used in order to refer to the bound base instance (provided the method being bound is not static).
The names of base method arguments (i.e., names after mapping) are only legal in the position given in §3.2.(b).
(e) Implicit parameter mappings
If parameter mappings should be omitted the following conditions must hold:
- each method parameter of the role method must conform to the corresponding parameter of the base method, and
- the result type of the base method must conform to the result type of the role method.
Here conformance includes translation polymorphism (cf. §3.3.(d)).
Parameter correspondence without parameter mapping is determined by declaration order not by names.
Two adjustments can, however, be performed implicitly:
- If the role method has more parameters than the base method, unused trailing parameters may be silently ignored.
- If the role method returns
void
, any result from the base method may be silently ignored.
Example code (Callout with Parameter Mapping):
1 | public team class MyTeamA { |
2 | public abstract class Role1 { |
3 | abstract void payEuro(float euro); |
4 | abstract float earnEuro(); |
5 | void idle(int seconds) { /* do nothing */ }; |
6 | } |
7 | Role1 boss, worker = // initialization omitted |
8 | public void transaction () { |
9 | boss.payEuro(worker.earnEuro()); |
10 | boss.idle(123); |
11 | } |
12 | } |
13 | public class Staff { // a base class |
14 | public void payDM (float dm) { … }; |
15 | public float earnDM () { … }; |
16 | public int doze() { … }; |
17 | // other methods omitted |
18 | } |
19 | public team class MySubTeam extends MyTeamA { |
20 | public class Role1 playedBy Staff { |
21 | void payEuro(float euro) -> void payDM(float dm) with { |
22 | euro * 1.95583f -> dm |
23 | } |
24 | float earnEuro() -> float earnDM () with { |
25 | result <- result / 1.95583f |
26 | } |
27 | idle => doze; // override existing implementation of idle() |
28 | } |
29 | void doit() { |
30 | transaction(); |
31 | } |
32 | } |
<< §3.1 Callout method binding | ↑ Table of Contents ↑ | §3.3 Lifting and lowering >> |
Effects:
MyTeamA
is declaratively complete and can be type checked because it only uses methods that are visible or declared within this context.MyTeamA.Role1
can, however, not be instantiated, because it is abstract.transaction
.transaction
, the call ofworker.earnEuro()
is forwarded to the corresponding base object using methodearnDM()
(binding declaration in line 24). The result is converted by "result / 1.95583f
" (line 25).transaction
, the call ofboss.payEuro()
is forwarded to the corresponding base object using methodpayDM()
(binding declaration in line 21). The parametereuro
is converted by "euro * 1.95583f
" (line 22).idle
is forwarded todoze
without any parameter mapping. This requiresdoze
to have a signature that is conformable to the signature ofidle
. In this case a role parameter and a base result are ignored.Using the
=>
operator, this binding overrides the existing implementation ofidle
.