18 Feb 2005 12:14
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/
RSS Feed