Visibility of accessor methods has no effect on the accessibility of its property. That is, if a property is public
and defined to have a getter, that getter may be defined as private
regardless.
Both getter and setter may access their physical field for data storage. The compiler ensures that this kind of field access does not go through the accessor method when made from within the accessor method itself, thus avoiding infinite recursion:
class Main { public var x(default, set):Int; function set_x(newX) { return x = newX; } static public function main() {} }
However, the compiler assumes that a physical field exists only if at least one of the access identifiers is default
or null
.
Define: Physical field
A field is considered to be physical if it is either
If this is not the case, access to the field from within an accessor method causes a compilation error:
class Main { // This field cannot be accessed because it is not a real variable public var x(get, set):Int; function get_x() { return x; } function set_x(x) { return this.x = x; } static public function main() {} }
If a physical field is indeed intended, it can be forced by attributing the field in question with the :isVar
metadata:
class Main { // @:isVar forces the field to be physical allowing the program to compile. @:isVar public var x(get, set):Int; function get_x() { return x; } function set_x(x) { return this.x = x; } static public function main() {} }
Trivia: Property setter type
It is not uncommon for new Haxe users to be surprised by the type of a setter being required to be
T->T
instead of the seemingly more naturalT->Void
. After all, why would a setter have to return something?The rationale is that we still want to be able to use field assignments using setters as right-side expressions. Given a chain like
x = y = 1
, it is evaluated asx = (y = 1)
. In order to assign the result ofy = 1
tox
, the former must have a value. Ify
had a setter returningVoid
, this would not be possible.