11

特定のオブジェクトと任意の「プロパティ」文字列を使用して、Groovyでネストされたプロパティを取得するための最良の方法は何でしょうか。私はこのようなことをしたいと思います:

someGroovyObject.getProperty("property1.property2")

他の人がこれをやりたいと思っている例を見つけるのに苦労したので、Groovyの基本的な概念を理解していないのかもしれません。これを行うには、エレガントな方法が必要なようです。

参考までに、Wicketには、PropertyResolverと呼ばれるまさに私が探している機能があり ます。http ://wicket.apache.org/apidocs/1.4/org/apache/wicket/util/lang/PropertyResolver.html

ヒントをいただければ幸いです。

4

4 に答える 4

25

Groovyにこれを行うための組み込みの方法があるかどうかはわかりませんが、ここに2つの解決策があります。Groovyコンソールでこのコードを実行してテストします。

def getProperty(object, String property) {

  property.tokenize('.').inject object, {obj, prop ->       
    obj[prop]
  }  
}

// Define some classes to use in the test
class Name {
  String first
  String second
}

class Person {
  Name name
}

// Create an object to use in the test
Person person = new Person(name: new Name(first: 'Joe', second: 'Bloggs'))

// Run the test
assert 'Joe' == getProperty(person, 'name.first')

/////////////////////////////////////////
// Alternative Implementation
/////////////////////////////////////////
def evalProperty(object, String property) {
  Eval.x(object, 'x.' + property)
}

// Test the alternative implementation
assert 'Bloggs' == evalProperty(person, 'name.second')
于 2011-03-30T16:14:02.540 に答える
3

Groovy Beansを使用すると、フィールドに直接アクセスできます。getter/setterメソッドを定義する必要はありません。それらはあなたのために生成されます。Beanプロパティにアクセスするたびに、getter/setterメソッドが内部的に呼び出されます。。@演算子を使用すると、この動作をバイパスできます。次の例を参照してください。

class Person {
    String name
    Address address
    List<Account> accounts = []
}

class Address {
    String street
    Integer zip
}

class Account {
    String bankName
    Long balance
}

def person = new Person(name: 'Richardson Heights', address: new Address(street: 'Baker Street', zip: 22222)) 
person.accounts << new Account(bankName: 'BOA', balance: 450)
person.accounts << new Account(bankName: 'CitiBank', balance: 300)

コレクションを扱っていない場合は、アクセスしたいフィールドを呼び出すだけです。

assert 'Richardson Heights' == person.name
assert 'Baker Street' == person.address.street
assert 22222 == person.address.zip

コレクション内のフィールドにアクセスする場合は、要素を選択する必要があります。

assert 'BOA' == person.accounts[0].bankName
assert 300 == person.accounts[1].balance​​​​​​​​​
于 2011-03-30T16:54:56.877 に答える
1

を使用することもできますpropertyMissing。これは、Groovyの組み込みメソッドと呼ばれるものです。

クラスでこれを宣言します。

def propertyMissing(String name) {
    if (name.contains(".")) {
        def (String propertyname, String subproperty) = name.tokenize(".")
        if (this.hasProperty(propertyname) && this."$propertyname".hasProperty(subproperty)) {
            return this."$propertyname"."$subproperty"
        }
    }
}

次に、必要に応じてプロパティを参照します。

def properties = "property1.property2"
assert someGroovyObject."$properties" == someValue

これは自動的に再帰的であり、メソッドを明示的に呼び出す必要はありません。これは単なるゲッターですが、パラメーターを使用して2番目のバージョンを定義し、セッターを作成することもできます。

欠点は、私が知る限り、のバージョンは1つしか定義できないためpropertyMissing、動的パスナビゲーションを使用するかどうかを決定する必要があることです。

于 2014-11-11T23:10:36.937 に答える
0

見る

https://stackoverflow.com/a/15632027/2015517

GStringの一部として使用できる${}構文を使用します

于 2013-03-26T11:40:30.300 に答える