2

私は、単純な構文と豊富なイベント ハンドラーを備えた変数バインディング/同期を提供する Groovy ライブラリを開発しています。まず、次の実行をアーカイブすることを目指しています。

def a = 1 
def b = 1
def c = 1
a bind { b + c }
assert a==2 & b==1 & c==1
b = 3
assert a==4 & b==3 & c==1
c = -1
assert a==2 & b==3 & c==-1

追加のクラスを提供するという Java FX のアプローチは避けたいのですが、この機能を使用してオブジェクトを強化したいと考えています。

オブジェクトの追跡を見つけることに行き詰まっています。Groovy には代入式のオーバーロード機能がありません。現在、私は重い AST 変換で解決策を見ています (おそらく dsld が役立つかもしれません)。

オブジェクト追跡やイベントなどがあるかもしれませんが、私は見逃しましたか?

4

1 に答える 1

1

スクリプトを使用してコードを書いていると思います。次のアイデアであなたが望んでいたことをしました:

  • を使用して値をキーにバインドする代わりに、と変数の両方を表すクラスをScript.binding作成する方が適切です。Variablevaluename
  • オブジェクトで呼び出されるすべてのメソッドは、Variableその値に委譲されます。
  • 更新操作と更新が必要なオブジェクトListenerへの参照をカプセル化するクラス。Variable
  • updateListeners()リスナーを更新するためのメソッド。
  • bind(closure)変数オブジェクトへのクロージャーをバイパスするだけのメソッド。それはほとんどドロップして次のように書くことができa { b + c }ます;

    class Listener { Closure operation; Variable variable }
    
    class Variable implements GroovyInterceptable { 
        String name; def value
    
        def invokeMethod(String method, args) {
            def var = args[0]
            var.class == Variable ? 
                    value."$method"(var.value) : value."$method"(var)
        }
    }
    
    Variable.metaClass.call = { Closure operation ->
        binding['listeners'] << 
                new Listener(operation: operation, variable: delegate)
        updateListeners()
    }
    
    def bind(Closure operation) { operation }
    
    def updateListeners() {
        binding.listeners.each {
            it.variable.value = it.operation()
        }
    }
    
    void setProperty(String prop, value) { 
        if (!binding.hasVariable('listeners')) binding['listeners'] = []
        binding[prop] = new Variable(name: prop, value: value)
        updateListeners()
    }
    

そして、あなたのテストは魔法のように機能しました。

于 2013-04-01T01:27:06.853 に答える