danielZ
danielZ

Reputation: 93

Groovy metaClass fails when overriding method called in constructor?

I just tried to write this simple code to test overriding methods using metaClass.

The code is here:

class Hello {

    public Hello()  
    {
        Foo()
    }

    public void Foo()
    {
        println "old"   
    }       

}

It has a Foo() method which simply prints "old" and it was called by the constructor.

Here's the test code:

class HelloTest {

    @Test
    public void test() {

        boolean methodFooWasCalled = false

        Hello.metaClass.Foo = {-> println "new"
            methodFooWasCalled = true
        }

        Hello hello = new Hello()

        assertTrue methodFooWasCalled == true

    }
}

I was expecting that the output should be "new" since Foo() has been overriden. But it still printed "old". Does anyone know why it fails? Thanks

Upvotes: 9

Views: 1239

Answers (1)

Will
Will

Reputation: 14529

The following works:

class Hello {
  Hello() {
    Foo()
  }
}

Hello.metaClass.Foo = {-> 
  println "new"
}

new Hello()

And so does the following:

class Hello {
  Hello() {
    invokeMethod('Foo', [] as Object[])
  }

  void Foo() { println "old" }
}

Hello.metaClass.Foo = {-> 
  println "new"
}

new Hello()

This one is interesting; the bar() call inside Foo() works, whilst the ones inside the constructor doesn't:

class Hello {
  Hello() {
    Foo()
    bar()
  }

  void Foo() { println "old foo"; bar() }
  void bar() { println "old bar" }
}

Hello.metaClass {
  Foo = {-> println "new foo" }
  bar = { println "new bar" }
}

new Hello()

It appears Groovy doesn't check metaclass' methods FIRST when on constructors. I think it is a bug, and i couldn't find any bug related to this. What about filling a JIRA?

Upvotes: 4

Related Questions