<< §3.4 Overriding access restrictions | ↑ Table of Contents ↑ |
§3.5 Callout to field
Also fields of a base class can be made accessible using a callout binding.
(a) Syntax
Using one of the callout modifiers get
or set
a role method
can be bound to a field of the role's base class:
1 | getValue -> get value; |
2 | setValue -> set value; |
3 | int getValue() -> get int value; |
where getValue
, setValue
are abstract role methods of
appropriate signatures and value
is a field of the bound base class.
A longer syntax is available, too (see line 3 above), which uses complete signatures.
For the left hand side §3.1.(c) applies, for the
right hand side, this longer version prepends the field type to the field name.
(b) Compatibility
A role method bound with the modifier get
should have no arguments
(it may have arbitrary arguments, which are silently ignored)
and should have a return type to which the base field is compatible.
A role method returning void will ignore the given value and thus has
no effect at all, which will be signaled by a compiler warning.
A role method bound with the modifier set
must have a first argument
that is compatible to the base field's type (additional arguments - if present -
are silently ignored) and must not declare a return type.
(c) Value mapping
Values can be mapped similar to parameter mappings in pure method bindings
(§3.2). Such mappings can be used to establish compatibility as required above.
In both get
and set
bindings, the base side value is denoted
by the field's name (lines 2 and 4 below).
1 | Integer getValue() -> get int val |
2 | with { result <- new Integer(val) } |
3 | void setValue(Integer i) -> set int val |
4 | with { i.intValue() -> val } |
(d) Effect
Callout-binding a role method to a base field generates an implementation for this role method, by which it acts as a getter or setter for the given field of the associated base object.
(e) Access control
For accessing an otherwise invisible field, the rules for
decapsulation (§3.4) apply accordingly.
Recall, that according to
JLS §8.3
fields may be hidden in sub-classes of a given base class. Therefore, it is relevant to know that a callout to
a field will always access the field that is visible in the exact base
class of the role class defining the callout. This is especially relevant
for accessing private fields.
(f) Shorthand definition
Just as in §3.1.(i) a shorthand definition allows to introduce a callout field access method without prior abstract declaration. This requires the callout field binding to specify types as in line 3 of §3.5.(a) above. The generated access method is static iff the bound base field is static.
A shorthand callout to field may optionally declare a visibility modifier, otherwise the generated method inherits the visibility modifier of the bound base field. No further modifiers are set. If a callout to field overrides an inherited method or callout, it must not reduce the visibility of the inherited method/callout.
(g) Callout override
Similar to method callouts a callout to field may override an existing role
method if and only if the token =>
is used instead of ->
(see §3.1.(e) and §3.1.(f)).
(h) Inferred callout
If a statement or expression within the body of a bound role class
uses a simple name or a name qualified by this
which can not be resolved using normal rules,
the compiler may infer to use a callout to field instead,
given that a field of the required name can be found in the role's declared baseclass.
If a callout to field has explicitly been declared it is used for the otherwise unresolved name, if and only if:
- the callout declares a role method name the is constructed from the token "set" for a setter or "get" for a getter plus the field name with capital first letter,
- the base field referenced by the callout has exactly the required name, and
- the callout kind (set/get) matches the application of the unresolved name as either the left-hand side of an assignment (set) or as an expression (get).
If a matching callout to field is not found, the compiler generates one automatically,
which has private
visibility.
If a callout to field has been inferred it is an error to directly invoke the implicitly generated callout accessor that is formed according to the above rules.
Per default inferred callout bindings are disabled, i.e., a compiler
must report these as an error. However, a compiler should allow to
configure reporting to produce a warning only (which can be suppressed
using a @SuppressWarnings("inferredcallout")
annotation),
or to completely ignore the diagnostic. See also §3.1.(j).
<< §3.4 Overriding access restrictions | ↑ Table of Contents ↑ |