Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

like image 467
danielZ Avatar asked Dec 15 '14 17:12

danielZ


1 Answers

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?

like image 141
Will Avatar answered Oct 20 '22 11:10

Will