Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Groovy property iteration

Tags:

groovy

In the Groovy code below I replace the values of the feck, arse, drink properties of an instance of Foo with those of an instance of Foo2

class Foo {     def feck = "fe"     def arse = "ar"     def drink = "dr"     }  class Foo2 {      def feck = "fe2"     def arse = "ar2"     def drink = "dr2" }   def f = new Foo() def f2 = new Foo2()   ["feck", "arse", "drink"].each {it ->     f."$it" = f2."$it" } 

Is there a better way to do this? My specific concern with the code above is that the property names are stored as strings in a list, which would likely be missed when (for example) using a refactoring IDE to change one of these property names.

like image 597
Dónal Avatar asked Sep 25 '09 14:09

Dónal


People also ask

How do I iterate a map in groovy?

We can iterate through entries using the each() and eachWithIndex() methods. The each() method provides implicit parameters, like entry, key, and value, which correspond to the current Entry.

What is a property in groovy?

When a Groovy class definition declares a field without an access modifier, then a public setter/getter method pair and a private instance variable field is generated which is also known as "property" according to the JavaBeans specification.

How do you use assert in if condition in Groovy?

The if's condition needs to be an expression. Assertions are for cases where you want it to fail loudly if what you're asserting is not true. Don't use assert unless you want it to throw an exception if the condition is not met.


2 Answers

I haven't yet found a good approach for excluding the read-only properties (i.e., metaClass, class), but if you want to set the value of all properties in the Foo instance that are also in the Foo2 instance you could do the following.

class Foo {     def feck = "fe"     def arse = "ar"     def drink = "dr"     }  class Foo2 {      def feck = "fe2"     def arse = "ar2"     def drink = "dr2" }   def f = new Foo() def f2 = new Foo2()   f2.properties.each { prop, val ->     if(prop in ["metaClass","class"]) return     if(f.hasProperty(prop)) f[prop] = val }  assert f.feck == "fe2" assert f.arse == "ar2" assert f.drink == "dr2" 
like image 69
John Wagenleitner Avatar answered Oct 06 '22 11:10

John Wagenleitner


Very late answer... however what about to take only the non synthetic declaredFields of Foo class. Using your approach:

class Foo {     def feck = "fe"     def arse = "ar"     def drink = "dr"     }  class Foo2 {     def feck = "fe2"     def arse = "ar2"     def drink = "dr2" }   def f = new Foo() def f2 = new Foo2()   Foo.declaredFields.findAll { !it.synthetic }*.name.each {it ->     f[it] = f2[it] }  assert f.feck == "fe2" assert f.arse == "ar2" assert f.drink == "dr2" 

If in refactoring something change for example in Foo but not in Foo2 then an Exception will be thrown from this code advising that something is wrong.

like image 26
albciff Avatar answered Oct 06 '22 10:10

albciff