groovy-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Jochen Theodorou <blackd...@gmx.org>
Subject Re: get/setProperty for POJOs
Date Wed, 11 Oct 2017 21:07:02 GMT
On 11.10.2017 19:11, Basurita wrote:
> Hi, I've been away from the Groovy world for some years.
> As of recently, I've been trying to add some behavior to Groovy scripts embedded in a
large Java codebase.
> A few things that I "half-remembered" striked me as odd.
> In this mail I want to ask about why Groovy does not honor certain methods for POJOs
> 
> My questions:
>    * Why does Groovy NOT honor get/setProperty for pojos?
>    * Why does it honor propertyMissing?
> 
> I'm sure there must be good/historical reasons for this incongruency, but I haven't been
able to google a good answer.
> And I don't think the answer will be "oh! we've never thought of that!" :-)
> If it were up to me, I would honor both or none...
> 
> And I'm not looking for "solutions" that add those methods through a metaClass blah blah
> I just would like a good rationale behind the way Groovy "naturally" handles properties
for POJOs

if we talk about foo.bar in Groovy then the semantics are the following 
(simplified):

* Iff foo is a GroovyObject, call foo.getProperty("bar"). The default 
implementation for this will use a property accessor to access the 
property. This accessor is normally the getter method.
* Iff foo is no GroovyObject we go directly to the meta class.

In the meta class the process is roughly the following:

step 1: Iff there is a getter getBar use getBar unless the property has 
been overwritten by meta programming
step 2: ... do some other things
step 3: Iff  step 1 and 2 do not apply and foo defines a 
propertyMissing(String) method, use that to get the property

The effect is the following:

> class Foo {
>   def bar = 1
>   def getProperty(String name) {2}
> }
> assert new Foo().bar == 2

Even though we have a getBar method,we are not using it, we are using 
the getProperty method. getProperty is called in the beginning of the 
dispatch.

> class Foo {
>   def bar = 1
>   def propertyMissing(String name) {2}
> }
> assert new Foo().bar == 1

See how we here call the getBar method, even though you defined a 
propertyMissing?

> class Foo {
>   def propertyMissing(String name) {2}
> }
> assert new Foo().bar == 2

> class Foo {
>   def getProperty(String name) {2}
> }
> assert new Foo().bar == 2

Only if the getter is missing the two seem to have the same semantics. 
But even then it is not the case. propertyMissing can be added by meta 
programming. For getProperty it must be a static method, which is then 
called in Java fashion.

Can you see the difference now?

If you want a historic view on this... getProperty was there first and I 
think back then the call to getProperty was actually hardcoded and 
directly written into the file. This changed early on with 
ScriptBytecodeAdapter, which catched more cases (foo is null for 
example), but the call is still a java call. And the original idea was I 
think if getProperty is there (it must be if it implements 
GroovyObjects, which all Groovy classes do) you can have the same 
semantics if you make the call from Java or from Groovy. propertyMissing 
was added with the advent of Grails, that did need a fallback method. 
This is not part of an interface, there is no Java based contract for 
this and for Java to call directly, thus we made this much more 
flexible. And I think in the future GroovyObject will (together with 
set/getProperty and get/setMetaclass) go away... at least the methods in 
there will.

[...]
> For reference, I created a POJO and added the following:

you added the POJO and marked how you want it to behave ;) That is 
important, because it is, the program will fail to pass the asserts. Why 
should be clear now I hope.
[...]

bye Jochen

Mime
View raw message