9

我对 groovys 方法重载行为有点困惑:鉴于下面的类和测试,我可以接受testAStringNulltestBStringNull 抛出模棱两可的方法调用异常,但为什么不是这样 testANulltestBNull

而且,更重要的是:为什么testBNull(null) call String foo(A arg)?我猜这个对象不知道它绑定到的变量的类型,但是为什么这个调用对 groovy 没有歧义,而其他调用呢?

(我希望我解释得足够好,生成这个最小的例子让我头疼。)

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

测试:

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

}
4

1 回答 1

21

这是 Groovy 的多调度机制的一个(有点鲜为人知的)奇怪之处,它试图调用“最合适的”方法,并结合提供的静态类型(在您的情况下为 A 或 B)不用作调度机制的一部分。当你声明 A a = null 时,你得到的不是 A 类型的空引用,而是对 NullObject 的引用。

最终,为了安全地处理重载方法的可能为空的参数,调用者必须强制转换参数,如

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

关于“Groovy 不是 Java 的超集”的讨论可能会对这个问题有所启发。

于 2012-09-21T18:04:04.040 回答