mirror of
https://github.com/adambard/learnxinyminutes-docs.git
synced 2025-08-06 23:06:49 +02:00
Merge pull request #275 from jdonaldson/master
More updates to the haxe guide
This commit is contained in:
@@ -16,40 +16,62 @@ references.
|
|||||||
Welcome to Learn Haxe 3 in 15 minutes. http://www.haxe.org
|
Welcome to Learn Haxe 3 in 15 minutes. http://www.haxe.org
|
||||||
This is an executable tutorial. You can compile and run it using the haxe
|
This is an executable tutorial. You can compile and run it using the haxe
|
||||||
compiler, while in the same directory as LearnHaxe.hx:
|
compiler, while in the same directory as LearnHaxe.hx:
|
||||||
haxe -main LearnHaxe3 -x out
|
$> haxe -main LearnHaxe3 -x out
|
||||||
|
|
||||||
|
Look for the slash-star marks surrounding these paragraphs. We are inside
|
||||||
|
a "Multiline comment". We can leave some notes here that will get ignored
|
||||||
|
by the compiler.
|
||||||
|
|
||||||
|
Multiline comments are also used to generate javadoc-style documentation for
|
||||||
|
haxedoc. They will be used for haxedoc if they immediately precede a class,
|
||||||
|
class function, or class variable.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Let's start with comments... this is a single line comment
|
// Double slashes like this will give a single-line comment
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
And this is multiline. Multiline comments are also used to generate
|
This is your first actual haxe code coming up, it's declaring an empty
|
||||||
javadoc-style documentation for haxedoc. They will be used if they precede
|
package. A package isn't necessary, but it's useful if you want to create a
|
||||||
a class, class function, or class variable.
|
namespace for your code (e.g. org.module.ClassName).
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
A package declaration isn't necessary, but it's useful if you want to
|
|
||||||
organize your code into modules later on. Also worth mentioning, all
|
|
||||||
expressions in Haxe must end in a semicolon:
|
|
||||||
*/
|
*/
|
||||||
package; // empty package, no namespace.
|
package; // empty package, no namespace.
|
||||||
|
|
||||||
|
/*
|
||||||
|
Packages define modules for your code. Each module (e.g. org.module) must
|
||||||
|
be lower case, and should exist as a folder structure containing the class.
|
||||||
|
Class (and type) names must be capitalized. E.g, the class "org.module.Foo"
|
||||||
|
should have the folder structure org/module/Foo.hx, as accessible from the
|
||||||
|
compiler's working directory or class path.
|
||||||
|
|
||||||
// if you import code from other files, it must be declared before the rest of
|
If you import code from other files, it must be declared before the rest of
|
||||||
// the code.
|
the code. Haxe provides a lot of common default classes to get you started:
|
||||||
|
*/
|
||||||
import haxe.ds.ArraySort;
|
import haxe.ds.ArraySort;
|
||||||
|
|
||||||
// you can import many classes/modules at once with "*"
|
// you can import many classes/modules at once with "*"
|
||||||
import haxe.ds.*;
|
import haxe.ds.*;
|
||||||
|
|
||||||
// you can also import classes in a special way, enabling them to extend the
|
/*
|
||||||
// functionality of other classes. More on this later.
|
You can also import classes in a special way, enabling them to extend the
|
||||||
|
functionality of other classes like a "mixin". More on 'using' later.
|
||||||
|
*/
|
||||||
using StringTools;
|
using StringTools;
|
||||||
|
|
||||||
// Haxe files typically define classes, although they can also define other
|
/*
|
||||||
// types of code... more on that later.
|
Typedefs are like variables... for types. They must be declared before any
|
||||||
|
code. More on this later.
|
||||||
|
*/
|
||||||
|
typedef FooString = String;
|
||||||
|
|
||||||
|
// Typedefs can also reference "structural" types, more on that later as well.
|
||||||
|
typedef FooObject = { foo: String };
|
||||||
|
|
||||||
|
/*
|
||||||
|
Here's the class definition. It's the main class for the file, since it has
|
||||||
|
the same name (LearnHaxe3).
|
||||||
|
*/
|
||||||
class LearnHaxe3{
|
class LearnHaxe3{
|
||||||
/*
|
/*
|
||||||
If you want certain code to run automatically, you need to put it in
|
If you want certain code to run automatically, you need to put it in
|
||||||
@@ -58,6 +80,7 @@ class LearnHaxe3{
|
|||||||
arguments above.
|
arguments above.
|
||||||
*/
|
*/
|
||||||
static function main(){
|
static function main(){
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Trace is the default method of printing haxe expressions to the
|
Trace is the default method of printing haxe expressions to the
|
||||||
screen. Different targets will have different methods of
|
screen. Different targets will have different methods of
|
||||||
@@ -67,8 +90,6 @@ class LearnHaxe3{
|
|||||||
Finally, It's possible to prevent traces from showing by using the
|
Finally, It's possible to prevent traces from showing by using the
|
||||||
"--no-traces" argument on the compiler.
|
"--no-traces" argument on the compiler.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
trace("Hello World, with trace()!");
|
trace("Hello World, with trace()!");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -76,16 +97,11 @@ class LearnHaxe3{
|
|||||||
a representation of the expression as best it can. You can also
|
a representation of the expression as best it can. You can also
|
||||||
concatenate strings with the "+" operator:
|
concatenate strings with the "+" operator:
|
||||||
*/
|
*/
|
||||||
trace(
|
trace( " Integer: " + 10 + " Float: " + 3.14 + " Boolean: " + true);
|
||||||
" Integer: " + 10 +
|
|
||||||
" Float: " + 3.14 +
|
|
||||||
" Boolean: " + true
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Remember what I said about expressions needing semicolons? You
|
In Haxe, it's required to separate expressions in the same block with
|
||||||
can put more than one expression on a line if you want.
|
semicolons. But, you can put two expressions on one line:
|
||||||
*/
|
*/
|
||||||
trace('two expressions..'); trace('one line');
|
trace('two expressions..'); trace('one line');
|
||||||
|
|
||||||
@@ -99,7 +115,6 @@ class LearnHaxe3{
|
|||||||
You can save values and references to data structures using the
|
You can save values and references to data structures using the
|
||||||
"var" keyword:
|
"var" keyword:
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var an_integer:Int = 1;
|
var an_integer:Int = 1;
|
||||||
trace(an_integer + " is the value for an_integer");
|
trace(an_integer + " is the value for an_integer");
|
||||||
|
|
||||||
@@ -111,7 +126,6 @@ class LearnHaxe3{
|
|||||||
the haxe compiler is inferring that the type of another_integer
|
the haxe compiler is inferring that the type of another_integer
|
||||||
should be "Int".
|
should be "Int".
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var another_integer = 2;
|
var another_integer = 2;
|
||||||
trace(another_integer + " is the value for another_integer");
|
trace(another_integer + " is the value for another_integer");
|
||||||
|
|
||||||
@@ -137,8 +151,14 @@ class LearnHaxe3{
|
|||||||
var a_string = "some" + 'string'; // strings can have double or single quotes
|
var a_string = "some" + 'string'; // strings can have double or single quotes
|
||||||
trace(a_string + " is the value for a_string");
|
trace(a_string + " is the value for a_string");
|
||||||
|
|
||||||
|
/*
|
||||||
|
Strings can be "interpolated" by inserting variables into specific
|
||||||
|
positions. The string must be single quoted, and the variable must
|
||||||
|
be preceded with "$". Expressions can be enclosed in ${...}.
|
||||||
|
*/
|
||||||
var x = 1;
|
var x = 1;
|
||||||
var an_interpolated_string = 'the value of x is $x';
|
var an_interpolated_string = 'the value of x is $x';
|
||||||
|
var another_interpolated_string = 'the value of x + 1 is ${x + 1}';
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Strings are immutable, instance methods will return a copy of
|
Strings are immutable, instance methods will return a copy of
|
||||||
@@ -148,6 +168,12 @@ class LearnHaxe3{
|
|||||||
var a_sub_string = a_string.substr(0,4);
|
var a_sub_string = a_string.substr(0,4);
|
||||||
trace(a_sub_string + " is the value for a_sub_string");
|
trace(a_sub_string + " is the value for a_sub_string");
|
||||||
|
|
||||||
|
/*
|
||||||
|
Regexes are also supported, but there's not enough space to go into
|
||||||
|
much detail.
|
||||||
|
*/
|
||||||
|
trace((~/foobar/.match('foo')) + " is the value for (~/foobar/.match('foo')))");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Arrays are zero-indexed, dynamic, and mutable. Missing values are
|
Arrays are zero-indexed, dynamic, and mutable. Missing values are
|
||||||
defined as null.
|
defined as null.
|
||||||
@@ -191,7 +217,7 @@ class LearnHaxe3{
|
|||||||
trace(m3 + " is the value for m3");
|
trace(m3 + " is the value for m3");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Haxe has many more common datastructures in the haxe.ds module, such as
|
Haxe has some more common datastructures in the haxe.ds module, such as
|
||||||
List, Stack, and BalancedTree
|
List, Stack, and BalancedTree
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -199,7 +225,6 @@ class LearnHaxe3{
|
|||||||
//////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////
|
||||||
// Operators
|
// Operators
|
||||||
//////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
trace("***OPERATORS***");
|
trace("***OPERATORS***");
|
||||||
|
|
||||||
// basic arithmetic
|
// basic arithmetic
|
||||||
@@ -218,7 +243,7 @@ class LearnHaxe3{
|
|||||||
trace((3 >= 2) + " is the value for 3 >= 2");
|
trace((3 >= 2) + " is the value for 3 >= 2");
|
||||||
trace((3 <= 2) + " is the value for 3 <= 2");
|
trace((3 <= 2) + " is the value for 3 <= 2");
|
||||||
|
|
||||||
//bitwise operators
|
// standard bitwise operators
|
||||||
/*
|
/*
|
||||||
~ Unary bitwise complement
|
~ Unary bitwise complement
|
||||||
<< Signed left shift
|
<< Signed left shift
|
||||||
@@ -252,6 +277,27 @@ class LearnHaxe3{
|
|||||||
trace("also not printed.");
|
trace("also not printed.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// there is also a "ternary" if:
|
||||||
|
(j == 10) ? trace("equals 10") : trace("not equals 10");
|
||||||
|
|
||||||
|
/*
|
||||||
|
Finally, there is another form of control structures that operates
|
||||||
|
at compile time: conditional compilation.
|
||||||
|
*/
|
||||||
|
#if neko
|
||||||
|
trace('hello from neko');
|
||||||
|
#elseif js
|
||||||
|
trace('hello from js');
|
||||||
|
#else
|
||||||
|
trace('hello from another platform!');
|
||||||
|
#end
|
||||||
|
/*
|
||||||
|
The compiled code will change depending on the platform target.
|
||||||
|
Since we're compiling for neko (-x or -neko), we only get the neko
|
||||||
|
greeting.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
trace("Looping and Iteration");
|
trace("Looping and Iteration");
|
||||||
|
|
||||||
// while loop
|
// while loop
|
||||||
@@ -310,13 +356,14 @@ class LearnHaxe3{
|
|||||||
generalized algebraic data types in enums (more on enums later).
|
generalized algebraic data types in enums (more on enums later).
|
||||||
Here's some basic value examples for now:
|
Here's some basic value examples for now:
|
||||||
*/
|
*/
|
||||||
var my_dog_name = 'fido';
|
var my_dog_name = "fido";
|
||||||
var favorite_thing = '';
|
var favorite_thing = "";
|
||||||
switch(my_dog_name){
|
switch(my_dog_name){
|
||||||
case "fido" : favorite_thing = 'bone';
|
case "fido" : favorite_thing = "bone";
|
||||||
case "rex" : favorite_thing = 'shoe';
|
case "rex" : favorite_thing = "shoe";
|
||||||
case "spot" : favorite_thing = 'tennis ball';
|
case "spot" : favorite_thing = "tennis ball";
|
||||||
case _ : favorite_thing = 'some unknown treat';
|
default : favorite_thing = "some unknown treat";
|
||||||
|
// case _ : "some unknown treat"; // same as default
|
||||||
}
|
}
|
||||||
// The "_" case above is a "wildcard" value
|
// The "_" case above is a "wildcard" value
|
||||||
// that will match anything.
|
// that will match anything.
|
||||||
@@ -345,10 +392,10 @@ class LearnHaxe3{
|
|||||||
trace("K equals ", k); // outputs 10
|
trace("K equals ", k); // outputs 10
|
||||||
|
|
||||||
var other_favorite_thing = switch(my_dog_name) {
|
var other_favorite_thing = switch(my_dog_name) {
|
||||||
case "fido" : 'teddy';
|
case "fido" : "teddy";
|
||||||
case "rex" : 'stick';
|
case "rex" : "stick";
|
||||||
case "spot" : 'football';
|
case "spot" : "football";
|
||||||
case _ : 'some unknown treat';
|
default : "some unknown treat";
|
||||||
}
|
}
|
||||||
|
|
||||||
trace("My dog's name is" + my_dog_name
|
trace("My dog's name is" + my_dog_name
|
||||||
@@ -358,6 +405,7 @@ class LearnHaxe3{
|
|||||||
//////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////
|
||||||
// Converting Value Types
|
// Converting Value Types
|
||||||
//////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////
|
||||||
|
trace("***CONVERTING VALUE TYPES***");
|
||||||
|
|
||||||
// You can convert strings to ints fairly easily.
|
// You can convert strings to ints fairly easily.
|
||||||
|
|
||||||
@@ -372,33 +420,93 @@ class LearnHaxe3{
|
|||||||
true + ""; // returns "true";
|
true + ""; // returns "true";
|
||||||
// See documentation for parsing in Std for more details.
|
// See documentation for parsing in Std for more details.
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////
|
||||||
|
// Dealing with Types
|
||||||
|
//////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
As mentioned before, Haxe is a statically typed language. All in
|
||||||
|
all, static typing is a wonderful thing. It enables
|
||||||
|
precise autocompletions, and can be used to thoroughly check the
|
||||||
|
correctness of a program. Plus, the Haxe compiler is super fast.
|
||||||
|
|
||||||
|
*HOWEVER*, there are times when you just wish the compiler would let
|
||||||
|
something slide, and not throw a type error in a given case.
|
||||||
|
|
||||||
|
To do this, Haxe has two separate keywords. The first is the
|
||||||
|
"Dynamic" type:
|
||||||
|
*/
|
||||||
|
var dyn: Dynamic = "any type of variable, such as this string";
|
||||||
|
|
||||||
|
/*
|
||||||
|
All that you know for certain with a Dynamic variable is that the
|
||||||
|
compiler will no longer worry about what type it is. It is like a
|
||||||
|
wildcard variable: You can pass it instead of any variable type,
|
||||||
|
and you can assign any variable type you want.
|
||||||
|
|
||||||
|
The other more extreme option is the "untyped" keyword:
|
||||||
|
*/
|
||||||
|
|
||||||
|
untyped {
|
||||||
|
var x:Int = 'foo'; // this can't be right!
|
||||||
|
var y:String = 4; // madness!
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
The untyped keyword operates on entire *blocks* of code, skipping
|
||||||
|
any type checks that might be otherwise required. This keyword should
|
||||||
|
be used very sparingly, such as in limited conditionally-compiled
|
||||||
|
situations where type checking is a hinderance.
|
||||||
|
|
||||||
|
In general, skipping type checks is *not* recommended. Use the
|
||||||
|
enum, inheritance, or structural type models in order to help ensure
|
||||||
|
the correctness of your program. Only when you're certain that none
|
||||||
|
of the type models work should you resort to "Dynamic" or "untyped".
|
||||||
|
*/
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////
|
||||||
// Basic Object Oriented Programming
|
// Basic Object Oriented Programming
|
||||||
//////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////
|
||||||
trace("***BASIC OBJECT ORIENTED PROGRAMMING***");
|
trace("***BASIC OBJECT ORIENTED PROGRAMMING***");
|
||||||
|
|
||||||
|
|
||||||
// create an instance of FooClass. The classes for this are at the
|
/*
|
||||||
// end of the file.
|
Create an instance of FooClass. The classes for this are at the
|
||||||
var instance = new FooClass(3);
|
end of the file.
|
||||||
|
*/
|
||||||
|
var foo_instance = new FooClass(3);
|
||||||
|
|
||||||
// read the public variable normally
|
// read the public variable normally
|
||||||
trace(instance.public_any + " is the value for instance.public_any");
|
trace(foo_instance.public_any + " is the value for foo_instance.public_any");
|
||||||
|
|
||||||
// we can read this variable
|
// we can read this variable
|
||||||
trace(instance.public_read + " is the value for instance.public_read");
|
trace(foo_instance.public_read + " is the value for foo_instance.public_read");
|
||||||
// but not write it
|
// but not write it
|
||||||
// instance.public_write = 4; // this will throw an error if uncommented:
|
// foo_instance.public_write = 4; // this will throw an error if uncommented:
|
||||||
// trace(instance.public_write); // as will this.
|
// trace(foo_instance.public_write); // as will this.
|
||||||
|
|
||||||
trace(instance + " is the value for instance"); // calls the toString method
|
trace(foo_instance + " is the value for foo_instance"); // calls the toString method
|
||||||
trace(instance.toString() + " is the value for instance.toString()"); // same thing
|
trace(foo_instance.toString() + " is the value for foo_instance.toString()"); // same thing
|
||||||
|
|
||||||
|
|
||||||
// instance has the "FooClass" type, while acceptBaseFoo has the
|
/*
|
||||||
// BaseFooClass type. However, since FooClass extends BaseFooClass,
|
The foo_instance has the "FooClass" type, while acceptBarInstance
|
||||||
// it is accepted.
|
has the BarClass type. However, since FooClass extends BarClass, it
|
||||||
BaseFooClass.acceptBaseFoo(instance);
|
is accepted.
|
||||||
|
*/
|
||||||
|
BarClass.acceptBarInstance(foo_instance);
|
||||||
|
|
||||||
|
/*
|
||||||
|
The classes below have some more advanced examples, the "example()"
|
||||||
|
method will just run them here.
|
||||||
|
*/
|
||||||
|
SimpleEnumTest.example();
|
||||||
|
ComplexEnumTest.example();
|
||||||
|
TypedefsAndStructuralTypes.example();
|
||||||
|
UsingExample.example();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -406,7 +514,7 @@ class LearnHaxe3{
|
|||||||
/*
|
/*
|
||||||
This is the "child class" of the main LearnHaxe3 Class
|
This is the "child class" of the main LearnHaxe3 Class
|
||||||
*/
|
*/
|
||||||
class FooClass extends BaseFooClass implements BaseFooInterface{
|
class FooClass extends BarClass implements BarInterface{
|
||||||
public var public_any:Int; // public variables are accessible anywhere
|
public var public_any:Int; // public variables are accessible anywhere
|
||||||
public var public_read (default,null): Int; // use this style to only enable public read
|
public var public_read (default,null): Int; // use this style to only enable public read
|
||||||
public var public_write (null, default): Int; // or public write
|
public var public_write (null, default): Int; // or public write
|
||||||
@@ -418,7 +526,7 @@ class FooClass extends BaseFooClass implements BaseFooInterface{
|
|||||||
|
|
||||||
// a public constructor
|
// a public constructor
|
||||||
public function new(arg:Int){
|
public function new(arg:Int){
|
||||||
super(); // call the constructor of the parent object, since we extended BaseFooClass
|
super(); // call the constructor of the parent object, since we extended BarClass
|
||||||
|
|
||||||
this.public_any= 0;
|
this.public_any= 0;
|
||||||
this._private = arg;
|
this._private = arg;
|
||||||
@@ -442,7 +550,7 @@ class FooClass extends BaseFooClass implements BaseFooInterface{
|
|||||||
}
|
}
|
||||||
|
|
||||||
// this class needs to have this function defined, since it implements
|
// this class needs to have this function defined, since it implements
|
||||||
// the BaseFooInterface interface.
|
// the BarInterface interface.
|
||||||
public function baseFunction(x: Int) : String{
|
public function baseFunction(x: Int) : String{
|
||||||
// convert the int to string automatically
|
// convert the int to string automatically
|
||||||
return x + " was passed into baseFunction!";
|
return x + " was passed into baseFunction!";
|
||||||
@@ -452,21 +560,217 @@ class FooClass extends BaseFooClass implements BaseFooInterface{
|
|||||||
/*
|
/*
|
||||||
A simple class to extend
|
A simple class to extend
|
||||||
*/
|
*/
|
||||||
class BaseFooClass {
|
class BarClass {
|
||||||
var base_variable:Int;
|
var base_variable:Int;
|
||||||
public function new(){
|
public function new(){
|
||||||
base_variable = 4;
|
base_variable = 4;
|
||||||
}
|
}
|
||||||
public static function acceptBaseFoo(b:BaseFooClass){
|
public static function acceptBarInstance(b:BarClass){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
A simple interface to implement
|
A simple interface to implement
|
||||||
*/
|
*/
|
||||||
interface BaseFooInterface{
|
interface BarInterface{
|
||||||
public function baseFunction(x:Int):String;
|
public function baseFunction(x:Int):String;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////
|
||||||
|
// Enums and Switch Statements
|
||||||
|
//////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/*
|
||||||
|
Enums in Haxe are very powerful. In their simplest form, enums
|
||||||
|
are a type with a limited number of states:
|
||||||
|
*/
|
||||||
|
|
||||||
|
enum SimpleEnum {
|
||||||
|
Foo;
|
||||||
|
Bar;
|
||||||
|
Baz;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Here's a class that uses it:
|
||||||
|
|
||||||
|
class SimpleEnumTest{
|
||||||
|
public static function example(){
|
||||||
|
var e_explicit:SimpleEnum = SimpleEnum.Foo; // you can specify the "full" name
|
||||||
|
var e = Foo; // but inference will work as well.
|
||||||
|
switch(e){
|
||||||
|
case Foo: trace("e was Foo");
|
||||||
|
case Bar: trace("e was Bar");
|
||||||
|
case Baz: trace("e was Baz"); // comment this line to throw an error.
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
This doesn't seem so different from simple value switches on strings.
|
||||||
|
However, if we don't include *all* of the states, the compiler will
|
||||||
|
complain. You can try it by commenting out a line above.
|
||||||
|
|
||||||
|
You can also specify a default for enum switches as well:
|
||||||
|
*/
|
||||||
|
switch(e){
|
||||||
|
case Foo: trace("e was Foo again");
|
||||||
|
default : trace("default works here too");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Enums go much further than simple states, we can also enumerate
|
||||||
|
*constructors*, but we'll need a more complex enum example
|
||||||
|
*/
|
||||||
|
enum ComplexEnum{
|
||||||
|
IntEnum(i:Int);
|
||||||
|
MultiEnum(i:Int, j:String, k:Float);
|
||||||
|
SimpleEnumEnum(s:SimpleEnum);
|
||||||
|
ComplexEnumEnum(c:ComplexEnum);
|
||||||
|
}
|
||||||
|
// Note: The enum above can include *other* enums as well, including itself!
|
||||||
|
|
||||||
|
class ComplexEnumTest{
|
||||||
|
public static function example(){
|
||||||
|
var e1:ComplexEnum = IntEnum(4); // specifying the enum parameter
|
||||||
|
/*
|
||||||
|
Now we can switch on the enum, as well as extract any parameters
|
||||||
|
it might of had.
|
||||||
|
*/
|
||||||
|
switch(e1){
|
||||||
|
case IntEnum(x) : trace('$x was the parameter passed to e1');
|
||||||
|
default: trace("Shouldn't be printed");
|
||||||
|
}
|
||||||
|
|
||||||
|
// another parameter here that is itself an enum... an enum enum?
|
||||||
|
var e2 = SimpleEnumEnum(Foo);
|
||||||
|
switch(e2){
|
||||||
|
case SimpleEnumEnum(s): trace('$s was the parameter passed to e2');
|
||||||
|
default: trace("Shouldn't be printed");
|
||||||
|
}
|
||||||
|
|
||||||
|
// enums all the way down
|
||||||
|
var e3 = ComplexEnumEnum(ComplexEnumEnum(MultiEnum(4, 'hi', 4.3)));
|
||||||
|
switch(e3){
|
||||||
|
// You can look for certain nested enums by specifying them explicitly:
|
||||||
|
case ComplexEnumEnum(ComplexEnumEnum(MultiEnum(i,j,k))) : {
|
||||||
|
trace('$i, $j, and $k were passed into this nested monster');
|
||||||
|
}
|
||||||
|
default: trace("Shouldn't be printed");
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
Check out "generalized algebraic data types" (GADT) for more details
|
||||||
|
on why these are so great.
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class TypedefsAndStructuralTypes {
|
||||||
|
public static function example(){
|
||||||
|
/*
|
||||||
|
Here we're going to use typedef types, instead of base types.
|
||||||
|
At the top we've declared the type "FooString" to mean a "String" type.
|
||||||
|
*/
|
||||||
|
var t1:FooString = "some string";
|
||||||
|
|
||||||
|
/*
|
||||||
|
We can use typedefs for "structural types" as well. These types are
|
||||||
|
defined by their field structure, not by class inheritance. Here's
|
||||||
|
an anonymous object with a String field named "foo":
|
||||||
|
*/
|
||||||
|
|
||||||
|
var anon_obj = { foo: 'hi' };
|
||||||
|
|
||||||
|
/*
|
||||||
|
The anon_obj variable doesn't have a type declared, and is an
|
||||||
|
anonymous object according to the compiler. However, remember back at
|
||||||
|
the top where we declared the FooObj typedef? Since anon_obj matches
|
||||||
|
that structure, we can use it anywhere that a "FooObject" type is
|
||||||
|
expected.
|
||||||
|
*/
|
||||||
|
|
||||||
|
var f = function(fo:FooObject){
|
||||||
|
trace('$fo was passed in to this function');
|
||||||
|
}
|
||||||
|
f(anon_obj); // call the FooObject signature function with anon_obj.
|
||||||
|
|
||||||
|
/*
|
||||||
|
Note that typedefs can have optional fields as well, marked with "?"
|
||||||
|
|
||||||
|
typedef OptionalFooObj = {
|
||||||
|
?optionalString: String,
|
||||||
|
requiredInt: Int
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Typedefs work well with conditional compilation. For instance,
|
||||||
|
we could have included this at the top of the file:
|
||||||
|
|
||||||
|
#if( js )
|
||||||
|
typedef Surface = js.html.CanvasRenderingContext2D;
|
||||||
|
#elseif( nme )
|
||||||
|
typedef Surface = nme.display.Graphics;
|
||||||
|
#elseif( !flash9 )
|
||||||
|
typedef Surface = flash8.MovieClip;
|
||||||
|
#elseif( java )
|
||||||
|
typedef Surface = java.awt.geom.GeneralPath;
|
||||||
|
#end
|
||||||
|
|
||||||
|
That would give us a single "Surface" type to work with across
|
||||||
|
all of those platforms.
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class UsingExample {
|
||||||
|
public static function example() {
|
||||||
|
|
||||||
|
/*
|
||||||
|
The "using" import keyword is a special type of class import that
|
||||||
|
alters the behavior of any static methods in the class.
|
||||||
|
|
||||||
|
In this file, we've applied "using" to "StringTools", which contains
|
||||||
|
a number of static methods for dealing with String types.
|
||||||
|
*/
|
||||||
|
trace(StringTools.endsWith("foobar", "bar") + " should be true!");
|
||||||
|
|
||||||
|
/*
|
||||||
|
With a "using" import, the first argument type is extended with the
|
||||||
|
method. What does that mean? Well, since "endsWith" has a first
|
||||||
|
argument type of "String", that means all String types now have the
|
||||||
|
"endsWith" method:
|
||||||
|
*/
|
||||||
|
trace("foobar".endsWith("bar") + " should be true!");
|
||||||
|
|
||||||
|
/*
|
||||||
|
This technique enables a good deal of expression for certain types,
|
||||||
|
while limiting the scope of modifications to a single file.
|
||||||
|
|
||||||
|
Note that the String instance is *not* modified in the run time.
|
||||||
|
The newly attached method is not really part of the attached
|
||||||
|
instance, and the compiler still generates code equivalent to a
|
||||||
|
static method.
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
We're still only scratching the surface here of what Haxe can do. For a formal
|
||||||
|
overiew of all Haxe features, checkout the [online
|
||||||
|
manual](http://haxe.org/manual), the [online api](http://api.haxe.org/), and
|
||||||
|
"haxelib", the [haxe library repo] (http://lib.haxe.org/).
|
||||||
|
|
||||||
|
For more advanced topics, consider checking out:
|
||||||
|
|
||||||
|
* [Abstract types](http://haxe.org/manual/abstracts)
|
||||||
|
* [Macros](http://haxe.org/manual/macros), and [Compiler Macros](http://haxe.org/manual/macros_compiler)
|
||||||
|
* [Tips and Tricks](http://haxe.org/manual/tips_and_tricks)
|
||||||
|
|
||||||
|
|
||||||
|
Finally, please join us on [the mailing list](https://groups.google.com/forum/#!forum/haxelang), on IRC [#haxe on
|
||||||
|
freenode](http://webchat.freenode.net/), or on
|
||||||
|
[Google+](https://plus.google.com/communities/103302587329918132234).
|
||||||
|
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user