Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unexpected behavior with overloaded methods

Tags:

groovy

I'm a bit confused about groovys method overloading behavior: Given the class and tests below, I am pretty okay with testAStringNull and testBStringNull throwing ambiguous method call exceptions, but why is that not the case for testANull and testBNull then?

And, much more importantly: why does testBNull(null) call String foo(A arg)? I guess the object doesn't know about the type of the variable it's bound to, but why is that call not ambiguous to groovy while the others are?

(I hope I explained well enough, my head hurts from generating this minimal example.)

class Foo {
    static class A {}
    static class B {}

    String foo(A arg) { return 'a' }

    String foo(String s, A a) { return 'a' }

    String foo(B arg) { return 'b' }

    String foo(String s, B b) { return 'b' }
}

Tests:

import org.junit.Test
import Foo.A
import Foo.B

class FooTest {
    Foo foo = new Foo()

    @Test
    void testA() {
        A a = new A()
        assert foo.foo(a) == 'a'
    }

    @Test
    void testAString() {
        A a = new A()
        assert foo.foo('foo', a) == 'a'
    }

    @Test()
    void testANull() {
        A a = null
        assert foo.foo(a) == 'a'
    }

    @Test
    void testAStringNull() {
        A a = null
        assert foo.foo('foo', a) == 'a'
    }

    @Test
    void testB() {
        B b = new B()
        assert foo.foo(b) == 'b'
    }

    @Test
    void testBString() {
        B b = new B()
        assert foo.foo('foo', b) == 'b'
    }

    @Test
    void testBNull() {
        B b = null
        assert foo.foo(b) == 'b'
    }

    @Test
    void testBStringNull() {
        B b = null
        assert foo.foo('foo', b) == 'b'
    }

}
like image 972
c089 Avatar asked Sep 21 '12 10:09

c089


People also ask

What happens when an overloaded method is invoked?

Overloaded methods are differentiated based on the number and type of parameter passed as arguments to the methods. If we try to define more than one method with the same name and the same number of arguments then the compiler will throw an error.

What is the most practical reason to create an overloaded method?

Method overloading increases the readability of the program. Overloaded methods give programmers the flexibility to call a similar method for different types of data. Overloading is also used on constructors to create new objects given different amounts of data.

What methods are called overloaded?

In Java, two or more methods may have the same name if they differ in parameters (different number of parameters, different types of parameters, or both). These methods are called overloaded methods and this feature is called method overloading.

How can you tell overloaded methods apart?

Overloaded methods are differentiated by the number and the type of the arguments passed into the method. In the code sample, draw(String s) and draw(int i) are distinct and unique methods because they require different argument types.


1 Answers

It's a (somewhat little-known) oddity of Groovy's multi-dispatch mechanism, which as attempting to invoke the "most appropriate" method, in combination with the fact that the provided static type (in your case A or B) is not used as part of the dispatch mechanism. When you declare A a = null, what you get is not a null reference of type A, but a reference to NullObject.

Ultimately, to safely handle possibly null parameters to overloaded methods, the caller must cast the argument, as in

A a = null
assert foo.foo('foo', a as A) == 'a'

This discussion on "Groovy Isn't A Superset of Java" may shed some light on the issue.

like image 105
GreyBeardedGeek Avatar answered Oct 07 '22 20:10

GreyBeardedGeek