Module System
In Haxe, each .hx file is considered a module. A module consists in an (optional) package declaration followed by import statements followed by several type declarations :
// module foo/Test.hx package foo; import haxe.Md5; class Test { // ... } class Sub { // ... } private class Priv { // ... }
A type declaration can be :
- a
classorinterface - an
enum - a
typedef
All types declared in a module belong to the package of this module, except if the type is declared as private : in that case, the type is only accessible from within the module, and its name will not conflit with other types in the same package.
So for instance, in the previous example, we have declared the types foo.Test, foo.Sub and foo._Test.Priv (private class).
An explicit error message will be displayed in case two different modules in the same package are declaring the same not-private type.
Import
When importing a module, you are actually importing all its not-private types inside the current global namespace :
import foo.Test; class Main { var t : Test; // reference the type Test inside module Test var s : Sub; // imported from module Test as well }
You can also import only a given type from a specific module :
import foo.Test.Sub; // only import Sub import foo.Test.Test; // only import Test
Types Reference
In order to access a type from within a module, you can use the fully qualified path foo.Test to access the Test class declared in the module foo/Test.hx.
var t : foo.Test; // .... t = new foo.Test();
But you can also use foo.Test.Sub to access the Sub class declared in the module :
var s : foo.Test.Sub; // ... s = new foo.Test.Sub();
Shortcuts
One commonly-used pattern of modules is to declare all the data structures that you need in a single module, so you can have them accessible with a single import.
Another pattern is to a create a module that only declares typedefs to make shortcuts for otherwise long-to-write types, for instance in Flash :
// module FastFlash.hx typedef MC = flash.display.MovieClip; typedef SPR = flash.display.Sprite; typedef BMP = flash.display.BitmapData; typedef EV = flash.display.Event; // etc.
Then you can simply do :
import FastFlash; class Button extends SPR { var animate : MC; //... }
Type Resolution Algorithm
Inside an expression, you can sometimes have very ambiguous accesses paths such as a.b.C.D.e which could mean many different things, for instance (this.a).b.C.D.e or (a.b.C.D).e (a.b.C.D being a module subtype).
Let's explain how such path is resolved :
- first, we do a variable lookup for the first element of the path (
ain our example ) . We are looking for (in that order) :- declared local variables
- member variables (current class and superclasses)
- static variables (only the current class)
- global variables (imported enums constructors)
- if we couldn't find a match, then we are looking for the most qualified module type (in that order) :
- type
Ddefined in modulea.b.C - static
Din typeCdefined in modulea.b.C
- type
- in the particular case where we have no package prefix (
C.D.efor example), we instead make a lookup using the current module package. If the current package isa.b, we will then look for :- type
Dina.b.C - static
Din typeCina.b.C - type
Dina.C - static
Din typeCina.C - type
DinC - type
Cin current module types - type
Cin imported types - type
Cin moduleC
- type