Groovy metaClass fails when overriding method call

2019-01-27 17:30发布

问题:

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

回答1:

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?