Reputation: 51
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'
Upvotes: 0
Views: 1628
Reputation: 346240
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.
Upvotes: 4
Reputation: 1
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.
Upvotes: 0
Reputation: 96767
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.
Upvotes: 0