Woozle Wuzzle
Nested functions in Java

I am always looking for ways to increase code clarity and reduce confusion and maintenance associated with "dangling methods". What's a dangling method? It's a method that is only used by another method to reduce code duplication. The scope of this method should therefore be local to only the calling function.

I tend to run into this problem when doing string manipulation. Currently I need to do a "last added character" for a CharBuffer. The only way to currently do this is to add a member function:

private char lastChar(final CharBuffer buffer)
{
    // determine if there are already chars in the buffer.  If
    // there are none, throw.
    if(buffer.position <= 0)
       throw new IndexOutOfBoundsException();
    /* else -- there are characters in the buffer */

    // retrieve the last character placed into the buffer
    // NOTE:  the above check ensures that there will be a char
    return buffer.get(buffer.position - 1);
}

to the class. This is no good since the scope of the method is too large. Large scope equals more time determining dependencies which equals more time to debug.

If Java allowed for nested functions, one could write:

private String normalize(final String string)
{
    ...

    // inner function for determining the last character
    // added to a buffer
    char lastChar(final CharBuffer buffer)
    { 
        ...
    };

    ...
 
        case '/':
            if(lastChar(buffer) != '/')
                ...

    ...
}

Having nested (or inner) functions in Java would help enormously. Kris Wehner brought up a Smalltalk technique which would be somewhat useful in this case. What do you think a solution to this problem would be?

Comments
Comment by Örjan Petersson at May 3, 2004 07:44 AM

Not exactly what you asked for but you can always use an anonymous inner class....

SomeClass {
...
private interface I {
char lastChar(CharBuffer b);
}

private String normalize(...) {
I i = new I() {
public char lastChar(...) {
}
}
char c = i.lastChar(...);
...
}
}

 

Comment by Rob Grzywinski at May 3, 2004 10:13 AM

You are most certainly correct that an inner class (essentially a command pattern) can be used to simulate what is desired in inner (or nested) functions. But what an inner class doesn't do for me is *completely* restrict the scope its use (since the interface has a larger scope) and that is what I am after. The more code that I can exclude from testing due to scope the better!

 

Comment by Örjan Petersson at May 4, 2004 04:26 AM

AFAIK, the only way to get rid of the interface I is by doing something like
Object o = new Object() {
char lastChar(String s) {
...
}
and use reflection to invoke lastChar() but it is nothing I would recommend :-)

Out of curiosity, if nested functions ever gets implemented, would you expect them to have access to local variables in the enclosing function (like anonymous inner classes)?

 

Comment by rgrzywinski at May 4, 2004 07:41 AM

The reflection call would indeed be ugly!

I would expect standard scoping rules to apply. So, yes, the inner functions would have access to local variables.

Thank you for your comments!

 

Comment by Anonymous at March 22, 2007 08:10 AM

It's been a few years since the last post. I would like to post the use of nested classes for your review.

private String normalize(final String string)
{
...

class MethodClass {
char lastChar(final CharBuffer buffer)
{
...
}
}
MethodClass myMethodClass = new MethodClass();

...

case '/':
if(myMethodClass.lastChar(buffer) != '/')
...

...
}

 

Comment by rgrzywinski at March 23, 2007 06:03 AM

What's funny about what you've proposed is that the "class" keyword was not allowed within functions back when I wrote this post otherwise I would have just implemented what you suggested and been a happy man.

Is this a recent change to the Java Language Specification, something that's now supported in IDE's (since I was using Eclipse at the time), or something else completely?

Thanks for your post!

 

Comment by Anonymous at March 23, 2007 08:28 AM

I'm sorry I can't answer your question as to when the "class" keyword started being supported. All I can say is I am using the lastest Eclipse IDE with Java 1.5, nothing fancy.

Thanks.

 

Comment by hmm at November 22, 2007 05:00 AM

Hmm, as far as I know local classes are allowed since JDK 1.1 and I'd be surprised if eclipse didn't support that in 2004.

 

Post a comment













Remember personal info?






Creative Commons License Unless otherwise expressly stated, all original material of whatever nature created by Rob Grzywinski and included in this weblog and any related pages, including the weblog's archives, is licensed under a Creative Commons License.