Search code examples
inheritancegroovyoptional-parametersoptional-arguments

Strange behavior with function overriding and optional params in Groovy


The behavior is best explained with a little code. In this example calling super.doSomething(t) from class y without the optional parameter results in it recursively calling itself (y.doSomething). Is this a bug or is there a explanation why leaving off the optional param and calling super results in a recursive call.

You can try it out here: https://tio.run/#groovy

class x {
    void doSomething(Integer x, Boolean n=false){
        println("Super ${n}")
    }
}

class y extends x {
    @Override
    void doSomething(Integer t, Boolean q=true){
        println("Sub")
        super.doSomething(t)  //Stack overflow - super.doSomething calls the subclass
        super.doSomething(t, q)  //Works as expected
    }
}

new y().doSomething(4)

Solution

  • The code below is basically what gets generated for what you have and this representation should help make sense of it:

    class X {
        void doSomething(Integer x) {
            // remember that for an instance of Y, this is
            // going to call doSomething(Integer, Boolean) in
            // the subclass (Y), not this class (X).
            doSomething x, false
        }
    
        void doSomething(Integer x, Boolean n) {
            println("Super ${n}")
        }
    }
    
    class Y extends X {
        void doSomething(Integer t) {
            doSomething t, true
        }
        @Override
        void doSomething(Integer t, Boolean q){
            println("Sub")
    
            // stack overflow because this calls doSomething(Integer) in
            // the parent class which is going to call
            // doSomething(Integer, Boolean), which will end up right back here
            super.doSomething(t)
    
            // no stack overflow
            super.doSomething(t, q)
        }
    }