Module System(모듈 시스템)

Haxe에서 각각의 .hx파일은 모듈로 간주합니다. 모듈은 하나의 패키지(선택사항), import 문, 여러 type선언 순으로 구성됩니다 :

// module foo/Test.hx
package foo;

import haxe.Md5;

class Test {
    // ...
}

class Sub {
    // ...
}

private class Priv {
    // ...
}

타입 선언의 종류 :

  • 클래스 또는 인터페이스
  • enum(열거형)
  • typedef

private 타입을 제외한 모든 타입은 패키지의 모듈에 속합니다. 따라서, 모듈내의 타입들은 접근가능한 것만 있고, 동일 패키지의 다른 타입과 이름이 중복되지 않아야 합니다.

예를 들어, 위 예제에서 foo.Test, foo.Subfoo._Test.Priv 타입을 선언했습니다.

동일 패키지내에서 다른 모듈들이 동일한 private가 아닌 타입으로 선언되면, 명시적인 에러메세지를 보일 것입니다.

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();

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
}

The package path must be absolute, you cannot use a package path relative to the current package.

When importing an enum, all its constructors will also be accessible as global variables.

If you want to import a single type from a module, you can use the following notation :

import foo.Test.Sub;

This will only import the Sub type declared in the given module, and will then prevent cluttering the module scope with several definitions.

Following the principles of shadowing, the latest types imported always have priority over the previous ones.

Import Whole-package

Instead of importing a single module, you can add a given package to the list of wildcards packages :

import haxe.*;

Everytime a type is not found (following the type resolution algorithm below), we will look at the wildcard packages for a match before displaying an error.

Following the principles of shadowing, the latest wildcard package have priority over the previous ones.

Import Globals

Starting from Haxe 2.11, you can also import classes statics and enum constructors into the global scope, by using :

import js.Lib.document;

This will make the static variable document of the js.Lib type a global variable accessible in the whole module directly.

You can also import all statics by using the following notation :

import js.Lib.*;

This will add all statics of the js.Lib type to the global scope.

Please note that we always use the principal module type (the one named the same as the module) for statics lookup. If you want to import some statics of a module sub type, you can use the following notation :

import foo.Test.Sub.*;

Following the principles of shadowing, the latest globals imported always have priority over the previous ones.

Import Alias

When importing a single type or a single global, you can define an alias name that will be used as a shortcut for this type or global :

import foo.Test in T;
import js.Lib.document in doc;

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 ( a in our example ) . We are looking for (in that order) :
    • declared local variables
    • member variables (current class and superclasses)
    • static variables (only the current class)
    • imported enums constructors
    • imported globals
  • if we couldn't find a match, then we are looking for the most qualified module type (in that order) :
    • type D defined in module a.b.C
    • static D in type C defined in module a.b.C
  • in the particular case where we have no package prefix (C.D.e for example), we instead make a package lookup
    • using the imported wildcard packages
    • using the current module package. If the current package is a.b, we will then look for :
      • type D in a.b.C
      • static D in type C in a.b.C
      • type D in a.C
      • static D in type C in a.C
      • type D in C
      • type C in current module types
      • type C in imported types
      • type C in module C

version #19756, modified 2013-09-17 14:46:27 by papapang