2016-08-12 5 views
1

私はHashMapのサブクラスであり、マップ内のいくつかのエントリのゲッタとセッタを持っている次のクラスを持っています。 HashMapのサブクラスでのプロパティアクセス

ご注意:このクラスは、私が使用するフレームワークから来ているを、私は変更することはできませんそれ

class Mapish extends HashMap { 
    static final PROPERTY_KEY = 'PROP' 

    def getProperty() { 
    get(PROPERTY_KEY) 
    } 

    def setProperty(def value) { 
    put(PROPERTY_KEY, value) 
    } 
} 

それは、このクラスのGroovyの地図プロパティ表記をオフにすることが可能であるようにプロパティアクセスによってゲッターが呼び出されますか?言い換えれば、次のことが成立するのですか?

def m = new Mapish() 
m.setProperty('value') 

assert m.property == 'value' // same as m.getProperty() 

と、次は私が地図をGroovyでマップとして動作しないようにする方法を知らないgroovy.lang.MissingPropertyException

m.PROP 

答えて

0

私はMetaClassImplisMapというプロパティを持っていることがわかってきた長いデバッグセッションの後。指定されたクラスがMapに割り当てられる場合、これはtrueです。この変数を使用すると、クラスにGroovy Map構文シュガーが作成されるため、falseに設定すると、クラスインスタンスはマップとして動作しません。唯一の難点は、フィールドがfinalので、反射が答えてくれてありがとうfalse

import java.lang.reflect.Field 
import java.lang.reflect.Modifier 

class Mapish extends HashMap { 
    static final PROPERTY_KEY = 'PROP' 

    def getProperty() { 
    get(PROPERTY_KEY) 
    } 

    def setProperty(def value) { 
    put(PROPERTY_KEY, value) 
    } 

} 

// this method does basically this: [email protected] = false 
// but since isMap is final the assignment throws exception 
def unmapify(Class c) { 
    def meta = c.metaClass.delegate 
    def isMapField = meta.class.getDeclaredField("isMap") 
    def modifiersField = Field.getDeclaredField("modifiers") 
    modifiersField.accessible = true 
    modifiersField.setInt(isMapField, isMapField.getModifiers() & ~Modifier.FINAL) 

    isMapField.accessible = true 
    isMapField.set(meta, false) 
} 

unmapify(Mapish) 

def m = new Mapish() 
m.setProperty('value') 

assert m.property == 'value' 

try { 
    m.PROP 
    assert false 
} catch (ignore) {} 
0

をスローしていました。たぶん、HashMapを拡張しないことを検討してください。このような何かはあなたが捜している行動を与えるだろう:

class Mapish { 
    static final PROPERTY_KEY = 'PROP' 
    private map = [:] 
    private getMap() { throw new groovy.lang.MissingPropertyException() } 
    private void setMap(def map) { throw new groovy.lang.MissingPropertyException() } 

    def getProperty() { 
    map[PROPERTY_KEY] 
    } 

    def setProperty(def value) { 
    map[PROPERTY_KEY] = value 
    } 
} 

その後、私はあなたが望むようにあなたのコードサンプルが正確に動作するように期待します。

+0

にそれを設定するために必要とされるということですが、それはライブラリから来ているように私の問題は、私は、クラスを変更できないということですアプリケーションが使用しています –

+0

ああ、あなたもあなたの質問文にその情報を追加したいかもしれません。決して気にせず、見ただけです。 – BalRog

+0

これはすでに冒頭に述べられていますが、私はそれをもっと目に見えるように編集します。 –

1

私はmeta-programmingが助けてくれると信じています。

は、次のことを考えてみましょう:

// original 

class Mapish extends HashMap { 
    static final PROPERTY_KEY = 'PROP' 

    def getProperty() { 
     get(PROPERTY_KEY) 
    } 

    def setProperty(def value) { 
     put(PROPERTY_KEY, value) 
    } 
} 

// meta-programming augmentation 

Mapish.metaClass.getProperty { String arg -> 
    if (arg == "property") { 
     delegate.getProperty() 
    } else { 
     throw new MissingPropertyException("illegal property: " + arg) 
    } 
} 

// test 

def m = new Mapish() 

m.setProperty("foo") 
assert "foo" == m.property 

try { 
    m.PROP 
    throw IllegalStateException("should not get here") 
} catch (MissingPropertyException ex) { 
    // println "caught exception as expected" 
} 
+0

ありがとうございますが、私の問題は、与えられたクラスに20個のプロパティがあるとすると、避けたいそれぞれのために 'if'を追加する必要があるということです。私は 'MetaClassImpl'をハックする方法を見つけました。そのため、Groovyはクラスを' Map' –