我想在Map中使用函数作为键:
var timers : Map<Void->Void, snow.api.Timer>;
但是Haxe不会编译:
抽象地图没有@:接受IMap&lt; Void - &gt;的函数Void,snow.api.Timer&gt;
有办法做到这一点吗?
答案 0 :(得分:3)
编写自定义实现很容易:
import haxe.Constraints;
class FunctionMap<K:Function,V> implements IMap<K,V> {
private var _keys : Array<K>;
private var _values : Array<V>;
public function new () {
_keys = [];
_values = [];
}
public function get(k:K):Null<V> {
var keyIndex = index(k);
if (keyIndex < 0) {
return null;
} else {
return _values[keyIndex];
}
}
public function set(k:K, v:V):Void {
var keyIndex = index(k);
if (keyIndex < 0) {
_keys.push(k);
_values.push(v);
} else {
_values[keyIndex] = v;
}
}
public function exists(k:K):Bool {
return index(k) >= 0;
}
public function remove(k:K):Bool {
var keyIndex = index(k);
if (keyIndex < 0) {
return false;
} else {
_keys.splice(keyIndex, 1);
_values.splice(keyIndex, 1);
return true;
}
}
public function keys():Iterator<K> {
return _keys.iterator();
}
public function iterator():Iterator<V> {
return _values
.iterator();
}
public function toString():String {
var s = new StringBuf();
s.add("{");
for( i in 0..._keys.length ) {
s.add('<function>');
s.add(" => ");
s.add(Std.string(_values[i]));
if( i < _keys.length - 1 )
s.add(", ");
}
s.add("}");
return s.toString();
}
private function index(key:K) : Int {
for (i in 0..._keys.length) {
if (Reflect.compareMethods(key, _keys[i])) {
return i;
}
}
return -1;
}}
答案 1 :(得分:1)
我刚刚在try.haxe.org中尝试了这个,编译器似乎不喜欢它,所以我猜测答案是“不”。
你可以通过一些cleverness来解决这个问题:
class Test {
static function main() {
var map:Map<VoidVoid,String>;
map = new Map<VoidVoid,String>();
var thing = {func:foo};
map.set(thing,"bar");
trace(map.get({func:foo})); //fails
trace(map.get(thing)); //succeeds;
}
static function foo():Void
{
}
}
typedef VoidVoid = {
var func:Void->Void;
}
但这不是一个理想的解决方案,因为将它包装在类似的类型中会使它失败,如果它不是完全相同的实例,即使里面的值是相同的。
我也试过制作一个Map<Dynamic,String>
,因为你可以填充函数引用,但这也不起作用。
此时我应该问,你想用这种方式解决什么问题?也许它可以通过其他方式更好地解决。