§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).