Haxe:具有抽象字段访问方法的绑定模式
Haxe: Binding pattern with abstract fields access methods
我想制作包装器来实现简单的数据绑定模式 -- 当一些数据已被修改时,所有已注册的处理程序都会收到通知。我已经开始使用这个(对于 js 目标):
class Main {
public static function main() {
var target = new Some();
var binding = new Bindable(target);
binding.one = 5;
// binding.two = 0.12; // intentionally unset field
binding.three = []; // wrong type
binding.four = 'str'; // no such field in wrapped class
trace(binding.one, binding.two, binding.three, binding.four, binding.five);
// outputs: 5, null, [], str, null
trace(target.one, target.two, target.three);
// outputs: 5, null, []
}
}
class Some {
public var one:Int;
public var two:Float;
public var three:Bool;
public function new() {}
}
abstract Bindable<TClass>(TClass) {
public inline function new(source) { this = source; }
@:op(a.b) public function setField<T>(name:String, value:T) {
Reflect.setField(this, name, value);
// TODO notify handlers
return value;
}
@:op(a.b) public function getField<T>(name:String):T {
return cast Reflect.field(this, name);
}
}
所以我遇到了一些令人沮丧的问题:包装对象的接口没有暴露给包装器,所以没有自动完成或严格的类型检查,一些必要的属性很容易被省略甚至拼写错误。
是否可以修复我的解决方案,或者我应该更好地转向宏?
您的摘要需要@:forward 元数据。但是,这不会使自动完成工作,除非您删除 @:op(A.B) 因为它会隐藏转发的字段。
编辑:我第一次将 @:forward 添加到您的摘要时似乎发生了阴影,之后自动完成工作正常。
我几乎建议在这里打开一个关于这个问题的问题。因为前段时间,有一个@:followWithAbstracts 元可用于摘要,它可以(或者可能是?)用于转发字段并同时调用@:op(a.b)。但这不是必须的,Haxe已经足够强大了。
abstract Binding<TClass>(TClass) {
public function new(source:TClass) { this = source; }
@:op(a.b) public function setField<T>(name:String, value:T) {
Reflect.setField(this, name, value);
// TODO notify handlers
trace("set: $name -> $value");
return value;
}
@:op(a.b) public function getField<T>(name:String):T {
trace("get: $name");
return cast Reflect.field(this, name);
}
}
@:forward
@:multiType
abstract Bindable<TClass>(TClass) {
public function new(source:TClass);
@:to function to(t:TClass) return new Binding(t);
}
我们这里使用multiType abstract来转发字段,但是resolved type其实是常规的abstract。实际上,您同时调用了完成工作和@:op(a.b)。
我想制作包装器来实现简单的数据绑定模式 -- 当一些数据已被修改时,所有已注册的处理程序都会收到通知。我已经开始使用这个(对于 js 目标):
class Main {
public static function main() {
var target = new Some();
var binding = new Bindable(target);
binding.one = 5;
// binding.two = 0.12; // intentionally unset field
binding.three = []; // wrong type
binding.four = 'str'; // no such field in wrapped class
trace(binding.one, binding.two, binding.three, binding.four, binding.five);
// outputs: 5, null, [], str, null
trace(target.one, target.two, target.three);
// outputs: 5, null, []
}
}
class Some {
public var one:Int;
public var two:Float;
public var three:Bool;
public function new() {}
}
abstract Bindable<TClass>(TClass) {
public inline function new(source) { this = source; }
@:op(a.b) public function setField<T>(name:String, value:T) {
Reflect.setField(this, name, value);
// TODO notify handlers
return value;
}
@:op(a.b) public function getField<T>(name:String):T {
return cast Reflect.field(this, name);
}
}
所以我遇到了一些令人沮丧的问题:包装对象的接口没有暴露给包装器,所以没有自动完成或严格的类型检查,一些必要的属性很容易被省略甚至拼写错误。
是否可以修复我的解决方案,或者我应该更好地转向宏?
您的摘要需要@:forward 元数据。但是,这不会使自动完成工作,除非您删除 @:op(A.B) 因为它会隐藏转发的字段。
编辑:我第一次将 @:forward 添加到您的摘要时似乎发生了阴影,之后自动完成工作正常。
我几乎建议在这里打开一个关于这个问题的问题。因为前段时间,有一个@:followWithAbstracts 元可用于摘要,它可以(或者可能是?)用于转发字段并同时调用@:op(a.b)。但这不是必须的,Haxe已经足够强大了。
abstract Binding<TClass>(TClass) {
public function new(source:TClass) { this = source; }
@:op(a.b) public function setField<T>(name:String, value:T) {
Reflect.setField(this, name, value);
// TODO notify handlers
trace("set: $name -> $value");
return value;
}
@:op(a.b) public function getField<T>(name:String):T {
trace("get: $name");
return cast Reflect.field(this, name);
}
}
@:forward
@:multiType
abstract Bindable<TClass>(TClass) {
public function new(source:TClass);
@:to function to(t:TClass) return new Binding(t);
}
我们这里使用multiType abstract来转发字段,但是resolved type其实是常规的abstract。实际上,您同时调用了完成工作和@:op(a.b)。