Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
462 views
in Technique[技术] by (71.8m points)

groovy - Unexpected behavior with overloaded methods

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'
    }

}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...