2017-03-09 6 views
4

ich Ambiguous error wenn ich versuche, einen Code zu verwenden, die mit funktionalen Argumenten überladene Methoden enthalten.Groovy Schließungen und überladene Methoden mit funktionellen Parametern

Ich schrieb einen kleinen Ausschnitt, die eine zweideutige Verhalten zeigt:

import java.util.function.BiConsumer 
import java.util.function.Consumer 

class Test { 

    static void main(String... args) { 
     execute({ x -> println("Consumer") }) 
     execute({ x, y -> println("BiConsumer") }) 
    } 

    static void execute(Consumer<Integer> c) { 
     c.accept(100) 
    } 

    static void execute(BiConsumer<Integer, Integer> c) { 
     c.accept(1, 2) 
    } 
} 

Ausgang (2.4.9 groovy):

Exception in thread "main" groovy.lang.GroovyRuntimeException: Ambiguous method overloading for method Test#execute. 
Cannot resolve which method to invoke for [class Test$_main_closure1] due to overlapping prototypes between: 
    [interface java.util.function.BiConsumer] 
    [interface java.util.function.Consumer] 
    at groovy.lang.MetaClassImpl.chooseMostSpecificParams(MetaClassImpl.java:3268) 
    at groovy.lang.MetaClassImpl.chooseMethodInternal(MetaClassImpl.java:3221) 
    at groovy.lang.MetaClassImpl.chooseMethod(MetaClassImpl.java:3164) 
    at groovy.lang.MetaClassImpl.pickStaticMethod(MetaClassImpl.java:1516) 
    at groovy.lang.MetaClassImpl.retrieveStaticMethod(MetaClassImpl.java:1412) 
    at org.codehaus.groovy.vmplugin.v7.Selector$MethodSelector.chooseMeta(Selector.java:553) 
    at org.codehaus.groovy.vmplugin.v7.Selector$MethodSelector.setCallSiteTarget(Selector.java:954) 
    at org.codehaus.groovy.vmplugin.v7.IndyInterface.selectMethod(IndyInterface.java:228) 
    at Test.main(Test.groovy:7) 

Aber es funktioniert mit Java-Lambda-Ausdrücke und ich verstehe nicht, wie man in dieser Situation Groovy-Closures benutzt.

Antwort

2

Sie müssen as XXX nach dem Schließungen setzen die Laufzeit einen Anhaltspunkt zu geben, wo Sie

execute({ x -> println("Consumer") } as Consumer) 
    execute({ x, y -> println("BiConsumer") } as BiConsumer) 

Sollte es tun

+0

Danke, es hilft in dieser Situation. Aber z.B. Wenn einige Java-Bibliotheken sich selbst geändert haben, indem sie neue überladene Methoden hinzugefügt haben, konnte das einen groovigen Code zerstören. –

+0

Sie können '@ CompileStatic' verwenden, um sie zur Kompilierzeit abzufangen –

0

mit vielleicht ein Closure:

execute(Closure <Integer> c) { 
    c (10) 
} 

execute (Closure <Integer, Integer> c) { 
    c (10, 30) 
} 
+2

Sie können gehen wollen 't Do 'Closure ', Closures akzeptieren nur einen generischen Parameter, der Rückgabetyp des Abschlusses –

+0

Lösung funktioniert nicht. – Rao

Verwandte Themen