【问题标题】:Haxe: Binding pattern with abstract fields access methodsHaxe:具有抽象字段访问方法的绑定模式
【发布时间】:2019-10-14 09:38:41
【问题描述】:

我想制作包装器来实现简单的数据绑定模式——虽然一些数据已被修改,但所有注册的处理程序都会收到通知。我从这个开始(针对 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);
    }
}

所以我有一些令人沮丧的问题:被包装对象的接口没有暴露给包装器,所以没有自动完成或严格的类型检查,一些必要的属性很容易被省略甚至拼写错误。

是否可以修复我的解决方案,或者我应该更好地转向宏?

【问题讨论】:

    标签: data-binding operator-overloading abstract haxe


    【解决方案1】:

    我几乎建议在这里打开一个关于这个问题的问题。因为前段时间,有一个可用于摘要的@: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 抽象来转发字段,但解析的类型实际上是常规抽象。实际上,您同时调用了完成工作和 @:op(a.b)。

    【讨论】:

    • 非常简洁的解决方案。它仍然允许滥用设置/获取缺少的字段和错误的类型分配,但自动完成工作正常。
    【解决方案2】:

    您的摘要需要@:forward 元数据。但是,除非您删除 @:op(A.B),否则这不会使自动完成工作,因为它会隐藏转发的字段。

    编辑:似乎在我第一次将 @:forward 添加到您的摘要时发生了阴影,之后自动完成工作得很好。

    【讨论】:

    • 我不认为转发在这种情况下真的有帮助,他想在设置字段时执行一些逻辑(“通知处理程序”注释)。 @:op(a.b) 仅用作摘要中不存在的字段的“备用”。
    • 转发真的无济于事。所有转发的字段都从重载的运算符中排除。此外,我无法创建与不同数据模型一样多的抽象包装器。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-09
    • 2012-06-20
    相关资源
    最近更新 更多