0

プロパティをクラスに動的に追加すると、クラスの各インスタンスは同じ値への参照で初期化されます (プロパティが正しく異なるアドレスにある場合でも、同じ参照値を共有したくありません)。

次に例を示します。

class SolarSystem {

    Planets planets = new Planets()

    static main(args) {
        SolarSystem.metaClass.dynamicPlanets = new Planets()

        // Infinite loop
//        SolarSystem.metaClass.getDynamicPlanets = {
//            if (!delegate.dynamicPlanets.initialized) {
//                delegate.dynamicPlanets = new Planets(initialized: true)
//            }
//
//            delegate.dynamicPlanets
//        }

        // No such field: dynamicPlanets for class: my.SolarSystem
//        SolarSystem.metaClass.getDynamicPlanets = {
//            if (!delegate.@dynamicPlanets.initialized) {
//                delegate.@dynamicPlanets = new Planets(initialized: true)
//            }
//
//            delegate.@dynamicPlanets
//        }

        SolarSystem.metaClass.getUniqueDynamicPlanets = {
            if (!delegate.dynamicPlanets.initialized) {
                delegate.dynamicPlanets = new Planets(initialized: true)
            }

            delegate.dynamicPlanets
        }

//        SolarSystem.metaClass.getDynamicPlanets = {
//            throw new RuntimeException("direct access not allowed")
//        }

        def solarSystem1 = new SolarSystem()
        println "a ${solarSystem1.planets}"
        println "b ${solarSystem1.dynamicPlanets}"
        println "c ${solarSystem1.uniqueDynamicPlanets}"
        println "d ${solarSystem1.dynamicPlanets}"

        println ''

        def solarSystem2= new SolarSystem()
        println "a ${solarSystem2.planets}"
        println "b ${solarSystem2.dynamicPlanets}"
        println "c ${solarSystem2.uniqueDynamicPlanets}"
        println "d ${solarSystem2.dynamicPlanets}"
    }
}

別のファイルで:

class Planets {
    boolean initialized = false
}

これを実行すると、次のように表示されます。

a my.Planets@4979935d
b my.Planets@66100363
c my.Planets@5e0feb48
d my.Planets@5e0feb48

a my.Planets@671ff436
b my.Planets@66100363
c my.Planets@651dba45
d my.Planets@651dba45

solarSystem2 では、2 つのオブジェクトが作成されたときに、「通常の」メンバー変数の惑星が異なるアドレスを持っていることに注意してください。ただし、動的に追加されたdynamicPlanets は、 solarSystem1が指していたのと同じオブジェクト (この場合、アドレス 66100363) を指しています。

動的ゲッター ( getUniqueDynamicPlanets ) でそれらを再割り当てでき、それで問題が解決します。

ただし、無限ループが発生するか、動的に追加されたプロパティに直接アクセスできないため、 getDynamicPlanetsゲッターをオーバーライドできません。

getDynamicPlanetsゲッターでこれを処理できるように、動的に追加されたプロパティに直接アクセスする方法はありますか? これに対するより良い戦略はありますか?見落としていたらすみません、いろいろ見てしまいました…

ありがとう

4

1 に答える 1

0

私はあなたの質問を100%理解しているとは確信していませんが、理解している場合は、getDynamicPlanetsクロージャーを明示的に0のパラメーターを持つように設定しようとしましたか?

SolarSystem.metaClass.getDynamicPlanets = {->  ... }

その前に引数のない がない場合、割り当てられ->た暗黙itのパラメーターがあり、それはゼロ引数メソッドではないため、javabean の getter/setter パターンに準拠していません。

于 2012-07-12T00:02:05.083 に答える