haxe使用变量向对象添加新键

时间:2016-07-25 17:58:48

标签: haxe

我已经定义了一个对象数据,用于存储我用于代码的各种数据。我想在运行时插入一个新房间。例如来自变量的新键“R200”,但到目前为止还没有。

 static public var data = 
 {
    room: {
        "R100": {monstersLeft: 2 }
    }
 }


// need to add the the object data :
// would like to reference is like: 
var newRoom = "R200";
???? data[newRoom ].monstersLeft = 5;

trace(data.R200.monstersLeft)

4 个答案:

答案 0 :(得分:5)

Haxe的anonymous structures只不过是无类型,有组织的数据集合。它们的结构一旦设置就是不可变的,只能修改属性值。在匿名结构上没有定义数组访问(括号表示法) - 而是使用点表示法。

由于匿名结构的无类型(动态)特性,在编译为静态目标时,它们可以有negative impact on performance

建议使用typedefstypedef extensions来组织和输入匿名结构。这样可以确保类型安全,并帮助编译服务器随时掌握任何打字错误。

要重新回到过去,通过使用maps和typedef可以最好地实现您的目标。 Maps允许您存储正确的键值对 - 通过方法和括号表示法 - 而typedef允许您键入数据结构,确保类型安全。

考虑到这一点,您的代码段可以重新创建如下:

class Test {
    static var data : Map<String, Room> = new Map<String, Room>();

    static function main() {
        data["R100"] = { monsterCount: 5 };
        data["R200"] = { monsterCount: 10 };

        trace(data["R100"].monsterCount);
        trace(data["R200"].monsterCount);
    }
}

typedef Room = {
    var monsterCount : Int;
}

Room现在是{ "monsterCount": (Int) }数据结构描述的类型,并映射到表示房间ID的字符串键。

Map API允许您从地图中设置和删除键值对,以及迭代键/值等。请务必查看API docs以获取更多信息。

编辑(2016-07-26)

lordkryss提供的答案完全有效。但是,有两个主要原因导致我没有提起reflection

  • Reflection是一个运行时功能,它的使用会不必要地使您的代码复杂化,并且不会为您提供所需的语法。
  • 在不同的目标上反思可能代价高昂且不可预测。

一般来说,你应该更好地反思动态而不是静态目标。在开发项目和决定目标平台时,请记住这一点。

我建议查看生成的来源,以便更好地了解反射的影响。您可以使用官方try.haxe.org沙箱查看Haxe 3.2.0生成的JavaScript源代码。还有unofficial sandbox也可以让你看到Haxe 3.3.0-rc.1生成的JavaScript源代码。

就个人而言,我不认为反射是您问题的可接受解决方案。我认为您的问题是找到适当的数据结构来表示您的数据。反射有其用处,但在这种情况下我不会推荐它。

答案 1 :(得分:4)

虽然Domagoj的解决方案可能是您问题的更好解决方案,但您可以使用https://github.com/macropin/django-registration/blob/master/registration/backends/default/views.py实际执行您在问题中提出的问题:

printf '%s' "1906 1d8b fb01 3e78 5c21 85db 58a7 0bf9 a6bf 1e42 cb59 95cd 99be 66f7 8758 cf46 315f 1607 66f7 6793 e5b3 61f9 fa03 952d  9101 b129 7180 6f1d ca93 3494 55e0 0e2e" \
  | xxd -r -p \
  | base64 -w 0

您可以尝试Reflection

上的代码

答案 2 :(得分:4)

考虑使用haxe.DynamicAccess它是Reflect的编译时包装器。因此它不会增加任何运行时开销,但提供了方便的语法来操作匿名结构。

import haxe.DynamicAccess;

typedef TRoom = {
    monstersLeft : Int
}


class Test {
    static public var data : {room:DynamicAccess<TRoom>} = {
        room: {
            "R100": {monstersLeft: 2}
        }
    };


    static function main() {

        var newRoom = "R200";
        data.room[newRoom] = {monstersLeft:10};

        trace(data.room['R200'].monstersLeft);
    }
}

您可以在此处试用:http://try.haxe.org/#cBc45

答案 3 :(得分:0)

您也可以使用StringMap,因为这就是您想要的:)地图应该像这样构建:[key => value, key => value ..]。请注意,您有array access这种类型的地图,它为您提供了所要求的语法。

class Test {
    static public var data = {
        rooms: [
            "R100" => {monstersLeft: 2}
        ]
    }

    static function main() {
        // add room
        data.rooms["R200"] = {monstersLeft: 5};

        // read room
        trace(data.rooms["R100"].monstersLeft); // 2
    }
}

演示:http://try.haxe.org/#2B855

这不是真正的问题,但为了完全避免反射,你可以使用数组而不是对象。这是一个架构上的变化,使用它的选择主要取决于你想通过它的id搜索房间的数量。如果经常这样,那么使用地图,否则可以考虑这个。

class Test {
    static public var data = {
        rooms: [ 
            {id:"R100", monstersLeft: 2},
        ]
    }

    static function main() {
        // add room
        var newRoom = {id:"R200", monstersLeft: 5};
        data.rooms.push(newRoom);

        // find rooms
        var room100 = findRoom("R100");
        trace(room100.monstersLeft); // 2
    }

    static function findRoom(id:String) {
        for (room in data.rooms) if (room.id == id) return room;
        return null;
    }
}

演示:http://try.haxe.org/#8bFfD

相关问题