Haxe的Dynamic数据类型

这个Dynamic数据类型像C#的动态类型,但是我C#的功力很弱,算新学了。

一、总述

官方教程上说:HAXE3编译器从不将类型推断为动态类型,因此用户必须对其进行明确说明。以前的haxe版本用于推断混合类型的数组,例如 var arr:array<dynamic>=[1,true,“foo”]。HAXE3之后就不能用了。

动态类型使用应该尽量少使用,效率不高,除非迫不得已。HAXE反射时候会使用动态类型,有时它是处理编译时未知的自定义数据结构时的最佳选择。如下面:

class Main {
  static function main() {
    var jsonData = '[1, 2, 3]';
    var json = haxe.Json.parse(jsonData);
    $type(json); // Unknown<0>
    for (i in 0...json.length) {  //可以用这种方式完成经典for循环
      // Array access is not allowed on
      // {+ length : Int }
      trace(json[0]);
    }
  }
}

这段代码是无法运行的,错误在于json[0]不能访问,因为var json 没有具体说明它的类型,因此haxe会推断parse的结果为一个匿名结构体,所以对于匿名结构体,则没有下表访问属性。因此要显式申明变量 json:Dynamic,但显式申明后,则没有了length属性了。

二、动态接口的实现

类可以实现Dynamic或Dynamic<T>,在前一种情况下,字段可以有任何类型,在后一种情况下,字段被约束为与参数类型兼容。看官方的例子:

class ImplementsDynamic
  implements Dynamic<String> {
  public var present:Int;
  public function new() {}
}

class Main {
  static public function main() {
    var c = new ImplementsDynamic();
    c.present = 1;//这是允许的,因为present是已经存在的
    // valid, assigned value is a String
    c.stringField = "foo";//这是可以的,虽然没有指定该字段,但是可以类似js一样,动态分配该字段
    // error, Int should be String
    c.intField = 1;//不能这么做,因为后增补的因为实现了Dynamaic<String>,所以不能
  }
}

实现动态(有或没有类型参数)的类也可以使用名为resolve的特殊方法。如果进行了读取访问,并且相关字段不存在,则使用字段名作为参数调用resolve方法:

class Resolve implements Dynamic<String> {
  public var present:Int;
  public function new() {}
//这个函数是回调函数,如果发现不存在的字段则自动调用
  function resolve(field:String) {
    return "Tried to resolve " +field;
  }
}

class Main {
  static public function main() {
    var c = new Resolve();
    c.present = 2;
	c.hello = "test";
    trace(c.present);
	trace(c.hello);
    trace(c.resolveMe);
  }
}

三、DynamicAccess

是一种抽象类型,用于处理匿名结构体,匿名结构体旨在通过字符串键保存对象集合。官方例子

class Main {
  static public function main() {
    var user:haxe.DynamicAccess<Dynamic> = {};

    // Sets values for specified keys.
    user.set("name", "Mark");
    user.set("age", 25);

    // Returns values by specified keys.
    trace(user.get("name")); // "Mark"
    trace(user.get("age")); // 25

    // Tells if the structure contains a specified key
    trace(user.exists("name")); // true
  }
}

如果我把haxe.DynamicAccess<Dynamic>去掉的话,则程序报错。在这点上我觉得不如其他动态语言,自动推断的能力有待提高。

四、Any类型

Any是一种兼容其他的数据类型。它有一个用途——保存任何类型的值,但要实际使用这些值,需要显式转换。

class Main {
  static function setAnyValue(value:Any) {
    trace(value);
  }

  static function getAnyValue():Any {
    return 42;
  }

  static function main() {
    // value of any type works
    setAnyValue("someValue");
    setAnyValue(42);
  
    var value = getAnyValue();
    $type(value); // Any, not Unknown<0>

    // won't compile: no dynamic field access
    // value.charCodeAt(0);

/**
public static function is( v : Dynamic, t : Dynamic ) : Bool;  is方法是这么申明的,用来判断类型是否一致
**/
    if (Std.is(value, String)) {
      // explicit promotion, type-safe
      trace((value : String).charCodeAt(0));//强制转型
    }
  }
}

它是动态的更类型安全的替代方案,因为它不支持字段访问或运算符,而且它绑定到单变形。因此,要使用实际值,需要将其显式升级为另一种类型。

猜你喜欢

转载自blog.csdn.net/keniv/article/details/88222842