views:

178

answers:

3

See the code below. Old instances of a class created before a method is added to the class using metaClass should not understand the method right? The assert statement below the 'PROBLEMATIC LINE' comment is executed when I think it should not be, as the old parentDir instance should not understand the blech() message.

// derived from http://ssscripting.wordpress.com/2009/10/20/adding-methods-to-singular-objects-in-groovy/

// Adding a method to a single instance of a class

def thisDir = new File('.')

def parentDir = new File('..')

thisDir.metaClass.bla = { -> "bla: ${File.separator}" }

assert thisDir.bla() == "bla: ${File.separator}" : 'thisDir should understand how to respond to bla() message'

try {
    parentDir.bla()
    assert false : 'parentDir should NOT understand bla() message'
} catch (MissingMethodException mmex) {
    // do nothing : this is expected
}

// Adding a method to all instances of a class

File.metaClass.blech = { -> "blech: ${File.separator}" }

try {
    thisDir.blech()
    assert false : 'old instance thisDir should NOT understand blech() message'
} catch (MissingMethodException mmex) {
    // do nothing : this is expected
}

try {
    parentDir.blech()
    // PROBLEMATIC LINE BELOW - THE LINE IS EXECUTED WHEN
    // I THINK AN EXCEPTION SHOULD HAVE BEEN THROWN
    assert false : 'old instance parentDir should NOT understand blech() message'
} catch (MissingMethodException mmex) {
    // do nothing : this is expected
}

thisDir = new File('.')
parentDir = new File('..')

try {
    thisDir.bla()
    assert false : 'new instance thisDir should NOT understand bla() message'
} catch (MissingMethodException mmex) {
    // do nothing : this is expected
}

assert "blech: ${File.separator}" == thisDir.blech() : 'new instance thisDir should understand blech() message'
assert "blech: ${File.separator}" == parentDir.blech() : 'new instance parentDir should understand blech() message'
A: 

The script ends it's execution with Caught: java.lang.AssertionError: old instance parentDir should NOT understand blech() message. Expression: false at x.run(x.groovy:35) . Were you not expecting the blech method to work? I don't see why not, since you're adding it to the File metaclass, and not just to the metaclass of an object.

Geo
A: 

The line:

parentDir.blech()

is executed successfully after blech() is added to File, as you say. But if that's the case then why wouldn't the call above it:

thisDir.blech()

work (not throw the exception that it does throw), since it is another instance of class File and blech() has already been added to File? Either both calls should fail with MissingMethodException or both should work. It's goofy that one works and the other doesn't.

Allen
A: 

the old parentDir instance should not understand the blech() message

That's not how metaclass works. You're apparently coming from a prototype-based OO language (JavaScript?). Groovy is not prototype-based. Changes to a class affect all instances of the class, including those created before the change was made.

Michael Borgwardt