haxe 第一期 入门骗 (谷歌翻译+转载)

来源:互联网 发布:windows安装centos引导 编辑:程序博客网 时间:2024/06/06 05:49
/* 
   欢迎在15分钟内学习Haxe 3。http://www.haxe.org 
   这是一个可执行的教程。
   您可以使用haxe编译器编译并运行它,
   而在与LearnHaxe.hx相同的目录中:   haxe -main LearnHaxe3 -x out 
   
   (只是把老外的文章谷歌翻译了而已,然后稍微整理了一下,可能有漏洞,还是推荐去看原文)
   
   (欢迎看原汁原味原网址,垃圾的我表示看不懂英文)
   https://github.com/jdonaldson/learnxinyminutes-docs/blob/master/haxe.html.markdown
   
   (附上一个看到的博客,里面文章对大家应该有帮助)
   http://blog.csdn.net/rocks_lee/article/details/10166573


*/


//我们从评论开始...这是一个单行评论


/* 
   这是多行的。多行注释也用于为haxedoc生成javadoc风格的文档。
   如果它们在类,类函数或类变量之前,它们将被使用。(传说中的代码提示)
*/


/* 
   这是你第一个实际的haxe代码,它宣布一个空的包。
   一个包不是必需的,
   但是如果要为代码创建一个命名空间
   (例如org.module.ClassName),这是非常有用的。*/ 


package;  //空包,没有命名空间。


/* 
   如果从其他文件导入代码,则必须在其余
   代码
之前声明。*/ 


import  haxe.ds.ArraySort ;


//您可以使用“*” 
import  haxe.ds. * 一次导入许多类/模块;


/* 您还可以以特殊方式导入类,使其能够扩展 其他类的功能。*/ 
   
using  StringTools ;


/* Typedefs类似于变量...。它们必须在任何代码之前声明。 */ 


typedef  FooString  =  String;


// Typedefs也可以使用“结构”类型,更多的也在以后!
typedef  FooObject  =  {  foo: String  } ;


class LearnHaxe01{
    /* 
       如果你希望某些代码自动运行,你需要把它放在
       一个静态的主要功能,并在编译器参数指定类。
       在这种情况下,我们在上面的编译器参数中指定了“LearnHaxe3”类。     */ 
  
   static function main(){
        /* 
           Trace是将haxe表达式打印到屏幕的默认方法。
  不同的目标将有不同的实现方法。例如,java,c ++,c#等将打印出来。
  Javascript将打印到console.log,flash将打印到一个嵌入的TextField。
  所有痕迹都附带默认换行符。
           最后,可以通过使用编译器上的“--no-traces”参数来防止跟踪显示。         */




       trace("Hello World, with trace()!");


        /* 
           Trace可以处理任何类型的值或对象。它将尝试最好地打印
           表达式的表示。您也可以连接字符串用“+”操作符:
         */ 
  
         trace(
            " Integer: " + 10 +
            " Float: " + 3.14 +
            " Boolean: " + true
            );


/*新增 抛出错误*/
try
{
throw "invalid foo"; //抛出错误后记得关闭运行的文件,否则一直编译报错,不明所以


}catch (e:String){}  //不同于as3的抛出错误

/*新增 确定值类型*/
var a:Int = 0;
$type(a);  //能输出值的类型,但是会报错


        /* 
           记住我所说的表达式需要分号吗?
  如果需要,您可以在一行上放置多个表达式。
         */ 
  
        trace('two expressions..'); trace('one line');


        ////////////////////////////////////////////////// //////////////// 
        //类型和变量
        /////////////////////////// ///////////////////// 

       trace("***Types & Variables***");




        /* 可以使用 “var”关键字保存数据结构的值和引用*/


        var an_integer:Int = 1;
        trace(an_integer + ' is the value for $an_integer');  
/*新增 注意上面这行代码,在字符串中加了一个 $ 后面接变量名就可以代表变量了
* 注意 仅在单引号内有效
* */


        /* 
           Haxe是静态类型的,所以“an_integer”被声明为具有“Int”类型,而其余的表达式将赋值为“1” 
           。在许多情况下不需要声明类型。这里,haxe编译器推断another_integer的类型应该是“Int”。
         */


        var another_integer = 2;
        trace(another_integer + " is the value for another_integer");




        // $ type()方法打印编译器分配的类型:
        $type(another_integer);


        //您也可以用十六进制表示整数:
        var hex_integer = 0xffffff;


        /* 
           Haxe使用Int和Float尺寸的平台精度。
  它还使用平台行为溢出。
           (使用特殊库可以使用其他数字类型和行为)         */


        /* 
           除了诸如整数,浮点数和布尔值之类的简单值之外,
           Haxe为常见的数据结构(如字符串,数组,列表和映射)提供标准库实现:         */


        var a_string = "some" + 'string';    //字符串可以有双引号或单引号,好像在调用的时候也没啥差别

        trace(a_string + " is the value for a_string");


        var x = 1;
        var an_interpolated_string = 'the value of x is $x';


        /* 
           字符串是不可变的,实例方法将返回部分或全部字符串的副本。
           (另请参见StringBuf类)。
         */ 
  
       var a_sub_string = a_string.substr(0,4);
       trace(a_sub_string + " is the value for a_sub_string");


        /* 
           数组是零索引的,动态的和可变的。缺少值被
           定义为null。
         */ 
  
/*新增  注意这里

* 在as3中,通常我们在写数组时会 

* var arr:Array = new Array(); 

* 但是在haxe里,这样是错误的,而且

* var a:Array = new Array<String>();

* 这样写同样会报错

* */ 
 
        var a = new Array<String>();   //包含字符串
        a[0] = 'foo';
        trace(a.length + " is the value for a.length");
        a[9] = 'bar';
        trace(a.length + " is the value for a.length (after modification)");
        trace(a[3] + " is the value for a[3]");


        /* 数组是*通用*,所以你可以用一个类型参数来指出它们包含的值:  */ 

        var a2 = new Array<Int>();// Ints的数组
        var a3 = new Array<Array<String>>();   //数组数组(字符串)。


        /* 地图是简单的键/值数据结构。键和值可以是任何类型。 */ 

        var m = new Map<String, Int>();   //键是字符串,值是Ints。
        m.set('foo', 4);

        //你也可以使用数组符号; 

/*新增 注释  总觉得这东西有点像dictionary
* 你可以通过一下几个方法访问m    
*  m['foo'];
*  m.get("foo");
* */

        m['bar'] = 5;

/*确定一个键值是否存在*/
        trace(m.exists('bar') + " is the value for m.exists('bar')");

        trace(m.get('bar') + " is the value for m.get('bar')");
        trace(m['bar'] + " is the value for m['bar']");

/*新增 注释 可以用下面这种方法来添加数据*/
var m2 =  ['foo' => 4, 'baz' => 6]; // Alternative map syntax
        trace(m2 + " is the value for m2");




        /* 
           记住,你可以使用类型推断。Haxe编译器将
           在您首次传递设置类型参数的参数时决定变量的类型。         */ 
  
var m3 = new Map();
        m3.set(6, 'baz'); // m3 is now a Map<Int,String>
        trace(m3 + " is the value for m3");


        /* 
           Haxe在haxe.ds模块中有更多常见的数据结构,例如
           List,Stack和BalancedTree 
         */




        ////////////////////////////////////////////////// //////////////// 
        //操作员
        ///////////////////////////// //////////////////// 
        trace("***OPERATORS***");


        //基本算术
        trace((4 + 3) + " is the value for (4 + 3)");
        trace((5 - 1) + " is the value for (5 - 1)");
        trace((2 * 4) + " is the value for (2 * 4)");
        trace((8 / 4) + " is the value for (8 / 3) (division always produces Floats)");
        trace((12 % 4) + " is the value for (12 % 4)");




        //基本比较
        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");
        trace((3 >= 2) + " is the value for 3 >= 2");
        trace((3 <= 2) + " is the value for 3 <= 2");


        //按位运算符
         /*
        ~       Unary bitwise complement
        <<      Signed left shift
        >>      Signed right shift
        >>>     Unsigned right shift
        &       Bitwise AND
        ^       Bitwise exclusive OR
        |       Bitwise inclusive OR
        */


        // increment 
var i = 0;
        trace("Increments and decrements");
        trace(i++); //i = 1. Post-Incrementation
        trace(++i); //i = 2. Pre-Incrementation
        trace(i--); //i = 1. Post-Decrementation
        trace(--i); //i = 0. Pre-Decrementation


        ////////////////////////////////////////////////// //////////////// 
        //控制结构
        //////////////////////////// //////////////////// 
         trace("***CONTROL STRUCTURES***");


        // if statements 
        var j = 10;
        if (j == 10){
            trace("this is printed");
        } else if (j > 10){
            trace("not greater than 10, so not printed");
        } else {
            trace("also not printed.");
        }


        // there is also a "ternary" if:
        (j == 10) ?  trace("equals 10") : trace("not equals 10");


        /* 
           最后,还有一种形式的控制结构
           在编译时运行:条件编译。
         */ 
  
#if neko
trace('hello from neko');
#elseif js
trace('hello from js');
#else
trace('hello from another platform!');
#end

        /* 
           编译后的代码将根据平台目标而有所不同。
           由于我们正在为neko(-x或-neko)进行编译,所以我们只得到了neko的
           问候语。
         */
  
trace("循环和迭代");
        // while loop 
        var k = 0;
        while(k < 100){
            // trace(counter); //将打印出数字0-99 
            k++;
        }


        // do-while loop 
         var  l = 0;
        do{
            trace("do statement always runs at least once");
        } while (i > 0);


        // 循环
        /* 
           Haxe中没有c-style for循环,因为它们容易出错,而不是必需的。
  相反,Haxe有一个使用迭代器的更简单和更安全的版本(更多在以后)。     
*/ 
  
        var m = [1,2,3];
        for (val in m){
            trace(val + " is the value for val in the m array");
        }


        //请注意,您可以使用范围
       
var n = ['foo', 'bar', 'baz'];
        for (val in 0...n.length){
            trace(val + " is the value for val (an index for m)");
        }




       trace("Array Comprehensions");


        //数组解析使您能够遍历数组
        //同时创建过滤器和修改。
         var filtered_n = [for (val in n) if (val != "foo") val];
        trace(filtered_n + " is the value for filtered_n");


        var modified_n = [for (val in n) val += '!'];
        trace(modified_n + " is the value for modified_n");


        var filtered_and_modified_n = [for (val in n) if (val != "foo") val += "!"];
        trace(filtered_and_modified_n + " is the value for filtered_and_modified_n");




        ////////////////////////////////////////////////// ////////////// 
        // //切换语句(值类型)
        //////////////////////// ////////////////////// 
        trace("***SWITCH STATEMENTS (VALUE TYPES)***");


        /* 
           在Haxe中的切换语句非常强大。除了处理
           诸如字符串和int之类的基本值之外,它们还可以处理
           枚举中的广义代数数据类型(稍后更多的枚举)。          
  这里有一些基本的价值实例:
         */ 
  
/*新增 注释 注意这里 switch语句没有break 要注意这里和其他语言的区别
* 但是我们可以这样写   case 1,2  用逗号把选项分开
* */
  
        var my_dog_name = "fido";
        var favorite_thing  = "";
        switch(my_dog_name){
            case "fido" : favorite_thing = "bone";
            case "rex"  : favorite_thing = "shoe";
            case "spot" : favorite_thing = "tennis ball";
            default     : favorite_thing = "some unknown treat";
            // case _   : "some unknown treat"; // same as default
        }
        //上面的“_”一个“通配符”值,将匹配任何东西。相当于default


        race("My dog's name is" + my_dog_name
                + ", and his favorite thing is a: "
                + favorite_thing);


        ////////////////////////////////////////////////// //////////////// 
        //表达陈述
        //////////////////////////// //////////////////// 
       
trace("***表达声明***");

        /*  Haxe控制语句非常强大,因为每个语句也是一个表达式*/

/*新增 注释 太强大 先吃一粒定心丸,可能有点颠覆我们的习惯*/


        // if statements 
        var k = if (true){
            10;
        } else {
            20;
        }




        trace("K equals ", k);   //输出10


        var other_favorite_thing = switch(my_dog_name) {
            case "fido" : "teddy";
            case "rex"  : "stick";
            case "spot" : "football";
            default     : "some unknown treat";
        }


        trace("My dog's name is" + my_dog_name
                + ", and his other favorite thing is a: "
                + other_favorite_thing);


        ////////////////////////////////////////////////// ////////////// 
        // //转换价值类型
        /////////////////////////// ///////////////////// 
       
trace("***转换类型***");


        //您可以很容易地将字符串转换为int。


        // string to integer 
        Std.parseInt("0");  //返回0 
        Std.parseFloat("0.4");  //返回0.4;


        // integer to string 
        Std.string(0);  //返回“0”; 
        //串联与字符串将自动转换为字符串。
         0 + "";    //返回“0”; 
        true + "";  //返回“true”; 
        //有关详细信息,请参阅Std中的解析文档。

/*新增 注释 Std 这个类提供了一些常用的数值运算 可以点进入类看看,方法不是很多,且提供了类型判断
* 在as3中 我比较习惯直接 用is 来判断类型,
* 但是在haxe中 is会报错,
* 但是我们可以使用 Std.is(123.1315,Int); 来判断
* */




        ////////////////////////////////////////////////// //////////////// 
        //处理类型
        /////////////////////////// /////////////////////////////////////


        /*


           如前所述,Haxe是一种静态类型的语言。总而言之
           ,静态打字是一件奇妙的事情。
  它启用自动完成,可以非常彻底地检查程序的正确性。
  另外,Haxe编译器超级快。你可能不会在等待它了。


           *无论如何*,有时您只希望编译器会让
           某些东西滑动,而不要在有限的情况下抛出类型错误。


           为了做到这一点,Haxe有两个单独的关键字。第一个是
           “Dynamic”类型:
         */ 
        var dyn: Dynamic = "any type of variable, such as this string";


        /* 
           所有你知道的一个动态变量是
           编译器不再担心它是什么类型。它就像一个
           通配符变量:你可以传递它,而不是任何变量类型,
           你可以分配任何你想要的变量类型。


           另一个更极端的选项是“无类型”关键字
         */


            untyped {
                var x:Int = 'foo';
                var y:String = 4;
            }


        /* 
           untyped关键字在整个* block *代码上运行,跳过
           任何可能需要的类型检查。该关键字应该
           非常谨慎地使用,例如在有条件编译的
           情况下,类型检查是一种阻碍。


           一般来说,跳过类型检查是*不*推荐。使用
           枚举,继承或结构类型模型来验证程序的正确性。
  只有当您确定所有类型型号都不工作时,您应该使用“动态”或“无类型”。         */


        ////////////////////////////////////////////////// ////////////// 
        //基础面向对象编程
        ////////////////////////// //////////////////// 
        
trace("***基于对象的面向对象编程***");


        /* 
           创建一个FooClass的实例。这些类在文件的末尾。         */


       var instance = new FooClass(3);


        //读取公共变量通常
        trace(instance.public_any + " is the value for instance.public_any");


        //我们可以读此变量
        trace(instance.public_read + " is the value for instance.public_read");
        //但不写它
        // instance.public_write = 4; //如果取消注释,这将抛出一个错误:
        // trace(instance.public_write); //就这样


        trace(instance + " is the value for instance");  //调用toString方法
        trace(instance.toString() + " is the value for instance.toString()");  // 一样




        /* 
           实例具有“FooClass”类型,而acceptBaseFoo具有
           BaseFooClass类型。但是,由于FooClass扩展了BaseFooClass,
           所以被接受。
         */ 
  
        BaseFooClass.acceptBaseFoo(instance);


        /* 
           下面的类有一些更高级的例子,“example()” 
           方法将在这里运行。
         */ 
  
        SimpleEnumTest.example();
        ComplexEnumTest.example();
        TypedefsAndStructuralTypes.example();
        UsingExample.example();


    }


}


/* 
  这是主要的LearnHaxe3类的“子类” 
*/ 
class FooClass extends BaseFooClass implements BaseFooInterface{
    public var public_any:Int;  //公共变量是随时随地访问
    public var public_read (default,null): Int;  //使用此样式仅启用公共读取
    public var public_write (null, default): Int; //或public write 
    public var property (get, set): Int;  //使用此样式来启用getter / setter


    //私有变量在类之外是不可用的。
    // see @:allow for around around this。
    var _private:Int;   //如果变量未标记为public,则变量为private


    // public 
    public function new(arg:Int){
        super();  //调用父对象的构造函数,因为我们扩展了BaseFooClass


        this.public_any= 0;
        this._private = arg;


    }


    // getter for _private 
    function get_property() : Int {
        return _private;
    }


    // setter for _private 
   function set_property(val:Int) : Int {
        _private = val;
        return val;
    }


    //每当将实例转换为字符串时调用的特殊函数。
   public function toString(){
        return _private + " with toString() method!";
    }




    //这个类需要定义这个函数,因为它实现了BaseFooInterface接口。
    public function baseFunction(x: Int) : String{
        // convert the int to string automatically
        return x + " was passed into baseFunction!";
    }
}


/* 
    一个简单的类来扩展
*/ 
class BaseFooClass {
    var base_variable:Int;
    public function new(){
        base_variable = 4;
    }
    public static function acceptBaseFoo(b:BaseFooClass){
    }
}


/* 
    一个简单的接口来实现
*/ 
interface BaseFooInterface{
    public function baseFunction(x:Int):String;
}


////////////////////////////////////////////////// ////////////// 
//枚举和切换语句
////////////////////////// //////////////////////////////////////


/* Haxe中的枚举非常强大。枚举是最简单的形式,它是一个数量有限的类型:*/


enum SimpleEnum {
    Foo;
    Bar;
    Baz;
}


//这是一个使用它的类:


class SimpleEnumTest{
    public static function example(){
        var e_explicit:SimpleEnum = SimpleEnum.Foo; //可以指定“完整”名称
        var  e  =  Foo ;  //但推论也会奏效。

switch(e){
            case Foo: trace("e was Foo");
            case Bar: trace("e was Bar");
            case Baz: trace("e was Baz"); // 注释此行以抛出错误。
        }


        /* 
           这与字符串上的简单值开关看起来没有什么不同。
           但是,如果我们不包括* all *的状态,
  编译器会抱怨。您可以通过注释上面的一行来尝试。


           您还可以为枚举开关指定默认值:
         */ 
        switch(e){
            case Foo: trace("e was Foo again");
            default : trace("default works here too");
        }
    } 
}


/* 
    枚举远远超过简单的状态,
我们也可以枚举 *构造函数*,
但是我们需要一个更复杂的枚举例子
*/ 
enum ComplexEnum{
    IntEnum(i:Int);
    MultiEnum(i:Int, j:String, k:Float);
    SimpleEnumEnum(s:SimpleEnum);
    ComplexEnumEnum(c:ComplexEnum);
}
//注意:上面的枚举可以包括*其他*枚举,包括自己!


class ComplexEnumTest{
    public static function example(){
        var e1:ComplexEnum = IntEnum(4); //指定枚举参数

        /* 现在我们可以打开枚举,并提取它可能有的任何参数。         */ 

        switch(e1){
            case IntEnum(x) : trace('$x was the parameter passed to e1');
            default: trace("Shouldn't be printed");
        }




        //这里的另一个参数本身就是枚举枚举枚举?
        var e2 = SimpleEnumEnum(Foo);
        switch(e2){
            case SimpleEnumEnum(s): trace('$s was the parameter passed to e2');
            default: trace("Shouldn't be printed");
        }


        //枚举一路向下
var e3 = ComplexEnumEnum(ComplexEnumEnum(MultiEnum(4, 'hi', 4.3)));
case ComplexEnumEnum(ComplexEnumEnum(MultiEnum(i,j,k))) : {
                trace('$i, $j, and $k were passed into this nested monster');
            }
            default: trace("(“不应打印”");
        }

        /* 查看“广义代数数据类型”(GADT),了解更多关于为什么这么大的细节。   */ 

    } 
}


class TypedefsAndStructuralTypes {
    public static function example(){

        //这里我们要使用typedef类型,而不是基类型。

         var t1:FooString = "some string";


        /* 
           我们可以使用typedef作为“结构类型”。
  这些类型由它们的字段结构定义,而不是类继承。
  这是一个名为“foo”的String字段的匿名对象:*/


        var fooObj = { foo: 'hi' };


        /* 
           记住在我们宣布FooObj typedef的顶部?
           由于fooObj与该结构相匹配,
  所以我们可以在任何需要“FooObject”的地方使用它。         */


        var f = function(fo:FooObject){
            trace('$fo was passed in to this function');
        }
        f(fooObj);  //用fooObj调用FooObject签名函数。


        /* 
           请注意,typedef还可以包含可选字段,标有“?”
 
            typedef OptionalFooObj = {
                ?optionalString: String,
                requiredInt: Int
           }
  
         */


        /* 
           Typedef与条件编译工作良好。例如,
           我们可以将其包含在文件的顶部:
  


#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; 
#结束

这将给我们一个单一的“表面”类型,以便在所有这些平台上使用。
        */ 
    } 
}


class UsingExample {
    public static function example() {


        /* 
           “using”import关键字是一种特殊的类导入,
  它改变了类中任何静态方法的行为。


           在这个文件中,我们将“using”应用于“StringTools”,
  它包含了一些用于处理String类型的静态方法。
         */ 
  
         trace(StringTools.endsWith("foobar", "bar") + " should be true!");


        /* 
           使用“using”导入时,第一个参数类型将使用该
           方法进行扩展。这意味着什么?那么,既然“的endsWith”具有第一 “字符串”,
  这意味着所有的字符串类型现在有的参数类型“的endsWith”的方法:
         */ 
  
        trace("foobar".endsWith("bar") + " should be true!");


        /* 
           这种技术可以为某些类型提供很好的表达,
           同时限制对单个文件的修改范围。

           请注意,String实例在运行时是*不*修改。
           新附加的方法不是附加
           实例的一部分,编译器仍然生成等效于静态方法的代码。      
*/ 
      }


}