jastrachan | 18 Feb 12:14 2005
Picon

quick summary of properties/fields/methods

After a long thread I thought I'd briefly summarise where I think we  
are...

The expression

foo.bar

in groovy is a property lookup of 'bar', or a field access depending on  
where it takes place. Inside the getter/setter method its a field,  
otherwise its a getter/setter property access. If you wanna be specific  
and say I really really want the field we can use

foo. <at> bar

If you really really wanna specify the getter/setter method we can use

foo.getBar()
foo.setBar(value)

There are a bunch of badly written classes in the JDK which we could  
try and fix somehow where zero argument methods with non-void return  
could be used as a property; but that feels more like a way to  
customise some MetaClass implementations to fix up some bad JDK classes  
than a core language issue for now? i.e. it feels like its an issue for  
the MetaClass of the JDK type to fix it to be a nicer POGO with real  
properties; than to complicate the property/field/method view in Groovy  
too much.

The edge case that has come up is if 'bar' is a field, with no  
getter/method called bar, then we can currently in Classic Groovy do  
this...

class Foo {
     def bar = { ... closure ... }

}

foo.bar()

This mechanism works in classic groovy by the MetaClass handling method  
dispatches; so from the MOP / MetaClass perspective there is a method  
called 'bar' on the class, it just doesn't look like it in the code. If  
there really is a bar() method, then the MetaClass uses that...

class Foo {
     def bar = { ... closure ... }

     String bar() {
	return "Cheese"
     }
}

assert foo.bar() == "Cheese"

So from the language perspective, foo.bar() is always a method call on  
Foo of the method 'bar'. Its just a MetaClass could define how this  
method dispatch works, and that could be implemented using some dynamic  
proxy or by delegating to a field which is a closure (such as when  
using Expando objects to simulate prototype-based languages like  
JavaScript etc).

Whether a MetaClass does something funky (delegating to a closure,  
doing markup or whatnot), it doesn't change the fact that the following  
rules hold...

foo.bar() 		// method call on Foo
foo.bar 		// property called 'bar' on Foo (unless inside the  
Foo.getBar() / Foo.setBar() methods)
foo. <at> bar 		// field access of 'bar' on Foo

So there's not really that much of a delta to Java other than property  
support (which folks are used to from JSP EL, JSF, Velocity, BeanShell,  
OGNL etc) other than we introduce an optional specific field/attribute  
access.

Here's a test case to see how this works in practice in New Groovy...

http://cvs.groovy.codehaus.org/viewrep/groovy/groovy/jsr/tck/test/misc/ 
FieldPropertyMethodDisambiguationTest.groovy?r=HEAD

Because we can provide hooks for classes to change the method  
dispatching, Foo.bar() can be implemented in a number of ways (new  
Groovy Methods we add to JDK types, interceptors, fields containing  
closures) is an implementation detail for Foo.

One interesting side effect from the above is that foo.bar and  
foo.bar() are quite different; one is a property access and one is a  
method call - so optional parenthesis only applies to methods with  
arguments.

Does that help clear things up?

James
-------
http://radio.weblogs.com/0112098/


Gmane