ObjectTeams/Java Language Definition - §4.
|
|
Table of |
§5. Team activation |
| §4. Callin Binding |
Notion of callin binding
Callin bindings realize a forwarding in the direction opposite to callout bindings (see §3). Both terms are chosen from the perspective of a role, which controls its communication with an associated base object.Technically, callin bindings are equivalent to weaving additional code (triggers) into existing base methods.
![]() |
|
| Callin | Methods of a base class may be intercepted by a callin binding (the base method "calls into" the role). |
![]() |
|
| Before/after/replace | The modifiers before, after, replace control the composition of original method and callin method. |
![]() |
|
| Activation | Callin bindings may be active or inactive according to §5. |
![]() |
|
§4.1. Callin method binding
(a) Method call interception
A role method may intercept calls to a base method by
a callin binding.
(b) Prerequisite: Class binding
A callin binding requires the enclosing class to be a role class
bound to a base class according to
§2.1. An unliftable role (see §2.3.4(a)) cannot define callin bindings. In that case callin bindings can only be introduced in sub-roles which (by an appropriately
refined
(c) Callin declarationplayedBy clause) disambiguate the lifting translation.
A callin binding composes an existing role method with a
given base method.
It may appear within the role class at any place where feature
declarations are allowed. It is denoted by
For callin modifiers see below (§ 4.2).
(d) Multiple base methodsrole_method_designator "
Just like with callout bindings, method designators may
or may not contain parameters lists and return type
but no modifiers;
also, each method designator must exactly and uniquely
select one method (cf. §3.1(c)).<-"
callin_modifier base_method_designator;For callin modifiers see below (§ 4.2).
Base method designators may furthermore enumerate a
list of methods. If multiple base methods are bound in one
callin declaration generally all signatures in this binding must be conform.
However, extraneous parameters from base methods may be ignored at the role.
For result types different rules exist, depending on the applied callin modifier (see next).
(e) Named callin bindingHowever, extraneous parameters from base methods may be ignored at the role.
For result types different rules exist, depending on the applied callin modifier (see next).
Any callin binding may be labeled with a name. The name of a callin binding is used for declaring precedence (§ 4.8). A named callin binding overrides any inherited callin binding (explicit and implicit (§ 1.3.1)) with the same name.
It is an error to use the same callin name more than once within the same role class.
(f) Callin to finalIt is an error to use the same callin name more than once within the same role class.
When binding to a final base method, the enclosing role must be played by the exact base class declaring the final
method. I.e., callin binding to a final method inherited from the base class's super-class is not allowed. This is motivated
by the fact that no sub-class may have a version of a final method with different semantics.
(g) Declared exceptions
It is an error if a role method to be bound by callin declares in its throws clause any exceptions that are not declared by the corresponding base method(s).
§4.2. Callin modifiers (before, after, replace)
(a) Method composition
The kind of method composition is controlled by adding one
of the modifiers before, after or replace after the
"
(b) Additive composition<-" token of the binding declaration.
The
In this case no data are transferred from the role to the base, so if the role method has a result, this will always be ignored.
(c) Replacing compositionbefore and after modifiers have the
effect of adding a call to the role method at the beginning or end
of the base method, resp.In this case no data are transferred from the role to the base, so if the role method has a result, this will always be ignored.
Example code:
|
Effects:
- Line 4 declares a callin binding for the role method
recalculateIncome()defined in line 3. - In combination with the role binding in line 2 this has the following effect:
- After every call of the method
Person.haveBirthdaythe methodCompany.recalculateIncomeis called.
The
In this case, if the base method declares a result, this should be provided by the role method. Special cases of return values in callin bindings are discussed in §4.3(e)
(d) Callin methodsreplace modifier causes only the role method to be
invoked, replacing the base method.In this case, if the base method declares a result, this should be provided by the role method. Special cases of return values in callin bindings are discussed in §4.3(e)
Role methods to be bound by a callin replacement binding must have
the modifier
A callin method must not declare its visibility using any of the modifiers
callin. This modifier is only allowed for methods
of a role class.
The only legal way to call a method with the callin modifier is
via a callin replace binding.
It is illegal for a callin method
- to be called directly,
- to be bound as callout, and
- to be bound as callin using
beforeorafter
A callin method must not declare its visibility using any of the modifiers
public, protected or private. Since callin methods can only be invoked via callin bindings such visibility control would not be useful.
§4.3. Base calls
Role methods with a
callin modifier should contain
a base call which uses the special name base
in order to invoke the original base method (original means: before replacement).
The syntax for base calls is
(b) Missing base callbase.m(),
which is in analogy to super calls.
A base.m() call must use the same name and signature
as the enclosing method. This again follows the rule, that roles
should never explicitly use base names, except in binding declarations.
For each callin method, the compiler uses some flow analysis to check whether
a base call will be invoked on each path of execution (analysis is very similar to the analysis for definite assignment
regarding final variables - JLS §16).
The compiler will issue a warning if a base call is missing either
on each path (definitely missing) or on some paths (potentially missing).
Instead of directly invoking a base call, a callin method may also call
its implicit super version using
(c) Duplicate base calltsuper.m() (see §1.3.1(f)). In this case the
flow analysis will transitively include the called tsuper version.
If a callin method contains several base calls, the compiler gives
a warning if this will result in duplicate base call invocations on all
paths (definitely duplicate) or on some paths (potentially duplicate).
Again tsuper calls are included in the flow analysis (see 4.3(b)).
(d) Parameter tunneling
If a base method has more parameters
than a callin method to which it is composed, additional
parameters are implicitly passed unchanged from the original
call to the base call (original means: before interception).
I.e., a call
(e) Fragile callin bindingbase.m() may invisibly pass additional
parameters that were provided by the caller, but are hidden from the
role method.
If a role method returns void, but the bound base method declares a
non-void result, this is reported as a fragile callin binding:
The result can still be provided by the base call, but omitting the
base call may cause problems depending on the return type:
- For reference return types
nullwill be returned in this case. - In the case of primitive return types this will cause a
ResultNotProvidedExceptionat run-time.
Comment:
Base calls can occur in callin methods that are not yet bound. These methods have no idea of the names of base methods that a sub-role will bind to them. Also multiple base methods may be bound to the same callin method. Hence the use of the role method's own name and signature. The language implementation translates the method name and signature back to the base method that has originally been invoked.Example code:
|
Effects:
- Line 2 defines a callin method which is bound to two methods of the base class
Point(see line 8). - The value passed to either setX or setY is checked if it is positive (line 3).
- Lines 4 and 6 show calls of the original method (base calls). While line 6 passes the original value, in the negative case (line 4) the passed value is made positive.
§4.4. Callin parameter mapping
(a) General case parameter mapping
The rules for mapping callin parameters and result type
are mainly the same as for callout bindings
(§3.2)
except for reversing
the
Callin bindings using
(b) Restrictions for callin replace bindings-> and <- tokens and
swapping left hand side and right hand side.Callin bindings using
before have no result mapping.
For result in after callin bindings
see §4.4(c) below.
The right-hand side of a parameter mapping may either be
the simple name of a base method argument without further
computation, or an arbitrary expression not containing
any base method argument.
Each base method argument must either appear as a simple name in exactly one parameter mapping or not be mapped at all. In the latter case, the original argument is "tunneled" to the base call, meaning, the callin method does not see the argument, but it is passed to the base method as expected.
If the base method declares a result, then
As stated above a fragile callin binding (§4.3(e)) is not allowed with a callin method that definitely has no base call (§4.3(b)). A callin replace binding is not fragile if it provides the base result using a result mapping.
A callin method bound with replace to a base method returning void must not declare a non-void result.
(c) Mapping the result of a base methodEach base method argument must either appear as a simple name in exactly one parameter mapping or not be mapped at all. In the latter case, the original argument is "tunneled" to the base call, meaning, the callin method does not see the argument, but it is passed to the base method as expected.
If the base method declares a result, then
- if the role method also declares a result,
resultmust be mapped to itself:result -> result - if the role method does not declare a result, an arbitrary
expression may be mapped to result:expressionIf in this situation no result mapping exists, the result of the base call is "tunneled" and passed to the original caller (see fragile callin binding above).
-> result
As stated above a fragile callin binding (§4.3(e)) is not allowed with a callin method that definitely has no base call (§4.3(b)). A callin replace binding is not fragile if it provides the base result using a result mapping.
A callin method bound with replace to a base method returning void must not declare a non-void result.
In an
(d) Multiple base methodsafter callin binding, the right-hand side
of a parameter mapping may use the identifier result
to refer to the result of the base method.
A callin binding listing more than one base method may use parameter
mappings with only the following restriction: if any base parameter
should be mapped this parameter must have the same name and type in all
listed base method designators. However, different parameter mappings for
different base methods bound to the same role method can be defined if
separate callin bindings are used.
§4.5. Lifting and lowering
(a) Call target translation
Invoking a role method due to a callin binding first
lifts the base object to the role class of the
callin binding, in order to obtain the effective call target. This is why callin bindings cannot be defined in roles
that are unliftable due to potential binding ambiguity (see §4.1(b) above and §2.3.4(a)).
(b) Parameter translation
During callin execution,
each parameter for which the role method expects a role
object is implicitly lifted to the declared role class.
(c) Result translation
Returning a role object from a callin method implicitly
lowers this object.
(d) Typing rules
A parameter mapping (implicit by parameter position or explicit
by a
These rules define translation polymorphism as introduced in §2.3.
(e) Role arrayswith clause) is well typed if
the right hand side conforms to the left hand side, either by
- type equality
- implicit primitive type conversion
- subtype polymorphism
- translation polymorphism, here: lifting;
however, withinreplacebindings step 1 of the smart lifting algorithm (§2.3.3(a)) is not applicable - or by a combination of the above.
with clause)
is well typed, if the value at the left hand conforms to the
right hand side according to the rules given above, except that
translation polymorphism here applies lowering instead of
lifting.These rules define translation polymorphism as introduced in §2.3.
For arrays of roles as parameters
§2.3(d) applies accordingly.
For arrays as return value
§2.2(e) applies.
(f) Base calls
For base calls these rules are reversed again, i.e., a
base call behaves like a callout binding.
§4.6. Overriding access restrictions
Callin bindings may also mention inaccessible methods
(cf. decapsulation §3.4).
Due to the reverse call direction this is relevant only for
base calls within
Comment:A base call to an inaccessible base method is considered harmless, since this is the originally intended method execution.
callin methods.
Base calls have unrestricted access to protected base methods.
Accessing a base method with private or default visibility is
also allowed, but signaled by a compiler warning.Comment:A base call to an inaccessible base method is considered harmless, since this is the originally intended method execution.
§4.7. Callin binding with static methods
The normal case of callin bindings refers to non-static methods on both
sides (base and role). Furthermore, in Java inner classes can not define
static methods. Both restrictions are relaxed by the following rules:
(a) Static role methods
A role class may define static methods (see also §1.2.1(f)).
(b) Binding static to static
A callin binding may bind a static role method to one or more
static base methods. It is, however, an error to bind a
static base method to a non-static role method, because such
binding would require to lift a base object that is not provided.
(c) before/after
In addition to the above,
(d) replacebefore and after
callin bindings may also bind a static role method to non-static base methods.
In contrast to §4.7(c) above, a
The following table summarizes the combinations defined above:
replace callin binding
cannot bind a static role method to a non-static base method.
| <- | base method | |||
| static | non-static | |||
| role method |
static | OK | before/after: OKreplace: illegal |
|
| non-static | illegal | OK | ||
Since static methods are not dynamically bound, overriding does not
apply in the normal semantics. Regarding callin bindings this has the
following consequences (assuming a role
RMid played by
BMid plus its super-class BSuper and its sub-class
BSub.
- If a static base method
BMid.mis bound by a callin binding this has no effect on any methodminBSub. - If a callin binding mentions a method
mwhich is not present inBMidbut resolves to a static method inBSuperthe binding only affects invocations asBMid.m()but notBSuper.m(). If the latter call should be affected, too, the callin binding must appear in a role class bound toBSuper, notBMid. - In order to bind two static base methods with equal signatures, one being
defined in a sub-class of the other one, two roles have to be defined
where one role refines the
playedByclause of the other role (say:public class RSub extends RMid playedBy BSub). Now each role may bind to the static base method accessible in its direct base-class.
§4.8. Callin precedence
If multiple callins from the same team refer to the same base method and also have the same callin modifier (
(a) Precedence declarationbefore, after or replace), the order in which the callin bindings shall be triggered has to be declared using a precedence declaration.
A precedence declaration consists of the keyword
A precedence declaration is only legal within a role or team class.
(b) Qualified and unqualified namesprecedence followed by a list of names referring to callin bindings (see § 4.1(e) for named callin bindings).A precedence declaration is only legal within a role or team class.
Within a role class a callin binding may be referenced by its unqualified name. A precedence declaration in a team class must
qualify the callin name with the name of the declaring role class. A team with nested teams may concat role class names. Elements
of a qualified callin name are seperated by ".".
The callin binding must be found in the role specified by the qualifying prefix or in the enclosing role for unqualified names, or any super class of this role (including implicit super classes § 1.3.1).
(c) Class based precedenceThe callin binding must be found in the role specified by the qualifying prefix or in the enclosing role for unqualified names, or any super class of this role (including implicit super classes § 1.3.1).
At the team level a precedence declaration may contain role class names without explicitely mentioning callin bindings in
order to refer to all callin bindings of the role.
(d) Multiple precedence statements
All precedence statements are collected at the outer-most team. At that level all precedence declarations involving the same
base method are merged using the C3 algorithm3. It is an error to declare incompatible precedence lists that cannot be merged by the C3 algorithm.
(e) Binding overriding
Precedence declarations may conflict with overriding of callin bindings (see § 4.1(e)): For each pair of callin bindings of which one callin binding overrides the other one, precedence declarations are not applicable,
since dynamic binding will already select exactly one callin binding.
It is an error to explicitly mention such a pair of overriding callin bindings in a precedence declaration.
When a class-based precedence declaration implicitly refers to a callin binding that is overridden by, or overrides any other callin binding within the same precedence declaration, this does not affect the fact, that the most specific callin binding overrides less specific ones.
It is an error to explicitly mention such a pair of overriding callin bindings in a precedence declaration.
When a class-based precedence declaration implicitly refers to a callin binding that is overridden by, or overrides any other callin binding within the same precedence declaration, this does not affect the fact, that the most specific callin binding overrides less specific ones.
![]() |
Callin binding example:
|
Effects
Provided the callin bindings are active (cf. §5) then:- the call in line 11 is intercepted by method
logof roleLogLogin. - the call target of
logis a role of typeLogLoginwhich is created by lifting the original call target (of typeDatabase) toLogLogin. - only parameter
uidis passed tolog(bound to formal parameterwhat). - within method
logthe base call (line 4) invokes the original method passing a modified uid (converted to lower case, cf. line 4) and the unmodified password, which is hidden from the callin method due to the parameter mapping in line 8.
Open issues:
The pattern language for specifying sets of base methods (§ 4.1(d)) has not been fixed yet. Possibly, this will not even be part of the language, but an external tool may be required to query base signatures and insert an explicit list of base methods.| References: |
3 Kim Barrett, Bob Cassels, Paul Haahr, David A. Moon, Keith Playford, P. Tucker Withington. A monotonic superclass linearization for Dylan. OOPSLA '96: Proceedings of the 11th ACM SIGPLAN conference on Object-oriented programming, systems, languages, and applications, pages 69-82, 1996.
|
|
Table of |
§5. Team activation |
© Stephan Herrmann, Christine Hundt
OT/J Version 1.0 — Last modified: Fri Mar 30 2007

