2012-09-21 27 views
9

ich ein bisschen verwirrt über groovys Methode Überlastung Verhalten bin: unterhalb der Klasse und Tests gegeben, bin ich ziemlich in Ordnung mit testAStringNull und testBStringNull mehrdeutig Methodenaufruf Ausnahmen werfen, aber warum ist das nicht der Fall für testANull und testBNull dann?unerwartetes Verhalten mit überladenen Methoden

Und, viel wichtiger: warum testBNull(null) Anruf String foo(A arg)? Ich denke, das Objekt weiß nichts über den Typ der Variablen, an die es gebunden ist, aber warum ist dieser Aufruf nicht mehrdeutig zu groovy während die anderen sind?

(ich hoffe, ich erklärte, gut genug, mein Kopf dieses minimal Beispiels von der Generierung weh tut.)

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

} 

Antwort

20

Es ist eine (etwas wenig bekannte) Kuriosität von Groovy Multi-Dispatch-Mechanismus, der versucht, die "am besten geeignete" Methode aufzurufen, in Kombination mit der Tatsache, dass der bereitgestellte statische Typ (in Ihrem Fall A oder B) nicht als Teil des Dispatch-Mechanismus verwendet wird. Wenn Sie A a = null deklarieren, erhalten Sie keine Nullreferenz vom Typ A, sondern einen Verweis auf NullObject.

Letztlich, um sicher möglicherweise null Parameter zu überladenen Methoden zu behandeln, muss der Anrufer das Argument werfen, wie in

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

Diese Diskussion über "Groovy Isn't A Superset of Java" auf der Frage etwas Licht kann.

+0

Gute Antwort. Hey, gibt es da nicht einen Bezug auf einen "Weg von der nächsten Klasse"? – Will

+0

Und wie schreibt man eine Methode, die null ausnimmt, ohne "a wie A" zu verwenden? Ich möchte keine Ausnahme von mehrdeutigen Methoden bekommen. –

Verwandte Themen