Access Control

Available in Haxe 2.11 and newer

Fields and methods in Haxe classes have two levels of access control:

  • public : this field is always accessible
  • private : this field can only be accessed by this class and its subclasses (this is the equivalent of protected in Java for instance)

Properties, however, have a little bit more control. See that page for more information.

When writing a library or a complex application, you may want finer control over which other classes are allowed to access your private fields. Other languages have specific keywords to provide package or namespace-wide access. Let's see what Haxe has to say about that!

Allowing Access

If you want to give access to the private fields of your class to another class/package, simply add @:allow metadata in front of your class declaration, like so:

package my.pack;

@:allow(my.pack)
class MyClass {
    private var foo : Int;
}

This will give access to all private fields of MyClass to all the classes in the package my.pack (and its sub-packages).

You can use as many @:allow declarations as you want, like so:

package my.pack;

@:allow(my.pack)  //Grants access to all classes in my.pack and its subpackages
@:allow(my.other.pack)  //Grants access to all classes in my.other.pack and its subpackages
@:allow(my.SpecificClass)  //Grants access to all instances of my.SpecificClass and any subclasses
@:allow(my.SpecificInterface)  //Grants access to all classes that implement my.SpecificInterface
class MyClass {
    private var foo : Int;
}

Getting Access

Typically, @:allow will cover your needs, but just in case we've provided a counterpart.

Let's say that you're using a library of some sort that, for whatever reason, you can't modify. Since you can't add @:allow(your.own.Code) metadata to the source code of the library in question, why not let your own code do the talking?

You can access the private fields of a class or package by using @:access metadata. In fact, you can even use multiple @:access declarations in exactly the same way as @:allow.

@:access(my.other.pack)
@:access(my.pack.MyClass)
class Main {
}

You might say that this goes against the wishes of the original author of the library's source code. And typically, you would be right. If the field is private, it may be implementation-specific behavior that could change between library versions. So, for the most part, don't muck around with other people's privates.

There comes that one time in a hundred, however, where you need to mess around with internal details. That's why we're letting you touch people's privates if you deem it necessary, possibly for things like profiling or debugging. The Haxe philosophy is that the developer knows what he or she is doing, and that any weird features like forcing public member access must be used explicitly.

Per-field access control

Both @:allow and @:access can also be declared in front of a particular field or method.

You can give access to only some specific private fields of your class :

class MyClass {
    // only give access to this specific private field
    @:allow(my.pack) private var foo : Int;
}

You can also only get access from within only specific methods of your class :

class Main {
    // only get access to MyClass private fields in this method
    @:access(my.pack.MyClass)
    function doSomethingSpecial() {
    }
}

Per-field access can also be used to limit the access you get to a single variable name :

class Main {
    // only get access to MyClass private field myPrivate in this method
    @:access(my.pack.MyClass.myPrivate)
    function doSomethingSpecial() {
    }
}

Read/Write Properties

The same ACL allows to get/grant access to private fields and methods, it will also work with read-only, write-only properties :

package my.pack;

class MyClass {
    // allow writing in the whole package
    @:allow(my.pack)
    public var foo(default,null) : Int;
}

On the choice of Metadata

This access-control language feature uses the Haxe metadata syntax instead of additional language-specific syntax.

Here's some reasons why :

  • additional syntax often adds complexity to the language parsing, and also adds (too) many keywords.
  • additional syntax requires additional learning by the language user, whereas metadata syntax is something that is already known
  • the metadata syntax is flexible enough to allow extension of this feature
  • the metadata can be accessed/generated/modified by Haxe macros

Of course, the main drawback of using metadata syntax is that you get no error report in case you misspell either the metadata key (@:acesss for instance) or the class/package name.

However, with this feature you will get an error when you try to access a private field that you are not allowed to, therefore there is no possibility for silent errors.

version #19733, modified 2013-09-07 01:03:08 by MrWint