2012-09-21 17 views
9

jestem trochę zdezorientowany o metodzie groovys przeciążenia zachowań: podany klasa i testy poniżej, jestem całkiem w porządku z testAStringNull i testBStringNull rzucanie wyjątki niejednoznaczne wywołanie metody, ale dlatego, że nie jest przypadek dla testANull i testBNull następnie?Nieoczekiwane zachowanie z przeciążonych metod

I co ważniejsze: dlaczego testBNull(null) dzwoń pod numer String foo(A arg)? Domyślam się, że obiekt nie wie o typie zmiennej, do której jest związany, ale dlaczego to wywołanie nie jest niejednoznaczne, aby wzbudzić emocje, podczas gdy inne są?

(Mam nadzieję, że wyjaśniłem wystarczająco dobrze, moja głowa boli od generowania tej minimalnej przykład.)

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

} 

Odpowiedz

20

Jest to (trochę mało znana) cudak z Groovy użytkownika mechanizm wielu wysyłek, który jako próbę przywołania "najbardziej odpowiedniej" metody, w połączeniu z faktem, że dostarczony typ statyczny (w twoim przypadku A lub B) nie jest używany jako część mechanizmu wysyłki. Kiedy zadeklarujesz A a = null, otrzymasz nie zerową referencję typu A, ale odwołanie do NullObject.

Ostatecznie, aby bezpiecznie obsługiwać możliwie zerowe parametry do przeciążonych metod, dzwoniący musi rzucić argument, podobnie jak w

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

Ta dyskusja na "Groovy Isn't A Superset of Java" może rzucić nieco światła na ten problem.

+0

Dobra odpowiedź. Hej, czy nie ma rzeczy związanych z "ścieżką z najbliższej klasy" związaną z tym? – Will

+0

A jak napisać metodę, która oprócz wartości null bez użycia "a as"? Nie chcę mieć wyjątku od niejednoznacznych metod. –

Powiązane problemy