Details
-
Type:
Improvement
-
Status:
Closed
-
Priority:
Major
-
Resolution: Fixed
-
Affects Version/s: None
-
Fix Version/s: 1.8-beta-1
-
Component/s: None
-
Labels:None
-
Number of attachments :
Description
This issue proposes an alternative way to meet requirement of GROOVY-3295 without the downsides discussed in that issue.
Groovy's Closure can be "coerced" into a java.util.concurrent.Callable but if we implemented that interface directly Groovy's method selection algorithm would find two methods in the example below with equal weighting:
// if Closure implemented Callable directly import java.util.concurrent.Callable Closure x = { -> println 'foo' } def a(Runnable r) { print 'runnable says '; r.run() } def a(Callable c) { print 'callable says '; c.call() } a(x) // => groovy.lang.GroovyRuntimeException: Ambiguous method overloading for method...
The proposal is to create a special interface:
package groovy.lang public interface GroovyCallable extends Callable { }
and have Closure implement that.
This interface would NOT typically be used in any user code, instead it just causes Callable to not be a direct interface for Closure and hence Runnable would be given preference over Callable in method selection yet Closure would still implement both Runnable and Callable for the purposes of Java integration. For APIs with both Runnable and Callable methods (like above), Runnable gets preference but you can still get the Callable method through casting or the "as" operator. For APIs with just Callable, the cast or "as" operator usage would no longer be required.
Issue Links
- supercedes
-
GROOVY-3295
Make Closure a java.util.concurrent.Callable
-
Activity
| Field | Original Value | New Value |
|---|---|---|
| Summary | Make Closure a java.util.concurrent.Callable (readdressed) | Make Closure a java.util.concurrent.Callable (re-addressed) |
| Description |
This issue proposes an alternative way to meet requirement of Groovy's {{Closure}} can be "coerced" into a {{java.util.concurrent.Callable}} but if we implemented that interface directly Groovy's method selection algorithm would find two methods in the example below with equal weighting: {code} // if Closure implemented Callable directly import java.util.concurrent.Callable Closure x = { -> println 'foo' } def a(Runnable r) { print 'runnable says '; r.run() } def a(Callable c) { print 'callable says '; c.call() } a(x) // => groovy.lang.GroovyRuntimeException: Ambiguous method overloading for method... {code} The proposal is to create a special interface: {code} package groovy.lang public interface GroovyCallable extends Callable { } {code} and have {{Closure}} implement that. This interface would *NOT* typically be used in any user code, instead it just causes {{Callable}} to not be a direct interface for {{Closure}} and hence {{Runnable}} would be given preference over {{Callable}} in method selection yet Closure would still implement both {{Runnable}} and {{Callable}} for the purposes of Java integration. For APIs with both {{Runnable}} and {{Callable}} methods (like above), {{Runnable}} gets preference but you can still get the {{Callable}} method through casting or the "as" operator. For APIs with just {{Callable}}, the cast or "as" operator usage would no longer be required. |
This issue proposes an alternative way to meet requirement of Groovy's {{Closure}} can be "coerced" into a {{java.util.concurrent.Callable}} but if we implemented that interface directly Groovy's method selection algorithm would find two methods in the example below with equal weighting: {code} // if Closure implemented Callable directly import java.util.concurrent.Callable Closure x = { -> println 'foo' } def a(Runnable r) { print 'runnable says '; r.run() } def a(Callable c) { print 'callable says '; c.call() } a(x) // => groovy.lang.GroovyRuntimeException: Ambiguous method overloading for method... {code} The proposal is to create a special interface: {code} package groovy.lang public interface GroovyCallable extends Callable { } {code} and have {{Closure}} implement that. This interface would *NOT* typically be used in any user code, instead it just causes {{Callable}} to not be a direct interface for {{Closure}} and hence {{Runnable}} would be given preference over {{Callable}} in method selection yet {{Closure}} would still implement both {{Runnable}} and {{Callable}} for the purposes of Java integration. For APIs with both {{Runnable}} and {{Callable}} methods (like above), {{Runnable}} gets preference but you can still get the {{Callable}} method through casting or the "as" operator. For APIs with just {{Callable}}, the cast or "as" operator usage would no longer be required. |
| Link |
This issue supercedes |
| Status | Open [ 1 ] | Resolved [ 5 ] |
| Assignee | Paul King [ paulk_asert ] | |
| Resolution | Fixed [ 1 ] |
| Status | Resolved [ 5 ] | Closed [ 6 ] |