Nieoczekiwane zachowanie przy przeciążonych metodach

Jestem trochę zdezorientowany co do sposobu przeciążania metody groovys: Biorąc pod uwagę poniższą klasę i testy, jestem całkiem w porządkutestAStringNull itestBStringNull rzucanie niejednoznacznych wyjątków wywołań metod, ale dlaczego tak nie jesttestANull itestBNull następnie?

I, co ważniejsze, dlaczegotestBNull(null) połączenieString foo(A arg)? Domyślam się, że obiekt nie wie o typie zmiennej, z którą jest związany, ale dlaczego to wywołanie nie jest dwuznaczne, by zagrać, podczas gdy inne są?

(Mam nadzieję, że wyjaśniłem to wystarczająco dobrze, moja głowa boli od wygenerowania tego minimalnego przykładu).

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

Testy:

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

}

questionAnswers(1)

yourAnswerToTheQuestion