groovy-notifications mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Eric Milles (JIRA)" <j...@apache.org>
Subject [jira] [Updated] (GROOVY-8433) Anonymous inner class results in cast exception with @Category applied
Date Fri, 05 Jan 2018 16:55:02 GMT

     [ https://issues.apache.org/jira/browse/GROOVY-8433?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]

Eric Milles updated GROOVY-8433:
--------------------------------
    Description: 
In working with a library that required extension of an SAM type to add a function binding,
I thought of using {{@Category}} to soften the integration.  What I found is that the implicit
{{this}} parameter that is passed to the constructor of an anon. inner class is being transformed
from the containing class to the category class due to the application of the {{@Category}}
transform.

Below I have boiled it down to the fewest moving parts I can.  {{LibraryContext}} is the type
that needs functions bound to it and the interface for doing so is {{LibraryFunction}} which
requires constructor params so I cannot use SAM Closure coercion.  My first take was to create
{{Factory.Binder}} to get the details out of the way.  That resulted in the cast exception
below.  When I converted {{Binder}} to define static methods with a first param of {{LibraryContext}}
all is well.

So I thought I would raise the issue that anon. inners and {{@Category}} are not currently
compatible.

{code}
Caught: org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object 'scripts.LibraryContext@6a28ffa4'
with class 'scripts.LibraryContext' to class 'scripts.Factory$Binder'
org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object 'scripts.LibraryContext@6a28ffa4'
with class 'scripts.LibraryContext' to class 'scripts.Factory$Binder'
	at scripts.Factory$Binder.bindStringFunction(CategoryTransform.groovy:18)
	at scripts.Factory$_create_closure1.doCall(CategoryTransform.groovy:10)
	at scripts.Factory$_create_closure1.doCall(CategoryTransform.groovy)
	at scripts.Factory.create(CategoryTransform.groovy:9)
	at scripts.Factory$create.call(Unknown Source)
	at scripts.CategoryTransform.run(CategoryTransform.groovy:42)
{code}

{code:java}
package scripts

class Factory {

  private Factory() {}

  static LibraryContext create() {
    LibraryContext context = new LibraryContext()
    use (Binder) {
      context.bindStringFunction('', { String[] strings -> '' })
    }
    return context
  }

  @Category(LibraryContext)
  private static class Binder {
    void bindStringFunction(String name, java.util.function.Function<String[], String>
func) {
      def stringFunction = new LibarayFunction(name, 0) { // cast exception here due to implicit
first param of "this"
        @Override
        String compute(String... args) {
            func.apply(args)
        }
      }

      this.bind(name, stringFunction)
    }
  }
}

class LibraryContext {
  void bind(String name, Object value) {
  }
}

abstract class LibarayFunction {
  LibarayFunction(String name, int argc) {
  }

  abstract String compute(String... argv);
}

Factory.create()
{code}


  was:
In working with a library that required extension of an SAM type to add a function binding,
I thought of using @Category to soften the integration.  What I found is that the implicit
"this" parameter that is passed to the constructor of an anon. inner class is being transformed
from the containing class to the category class due to the application of the @Category transform.

Below I have boiled it down to the fewest moving parts I can.  {{LibraryContext}} is the type
that needs functions bound to it and the interface for doing so is {{LibraryFunction}} which
requires constructor params so I cannot use SAM Closure coercion.  My first take was to create
{{Factory.Binder}} to get the details out of the way.  That resulted in the cast exception
below.  When I converted {{Binder}} to define static methods with a first param of {{LibraryContext}}
all is well.

So I thought I would raise the issue that anon. inners and @Category are not currently compatible.

{code}
Caught: org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object 'scripts.LibraryContext@6a28ffa4'
with class 'scripts.LibraryContext' to class 'scripts.Factory$Binder'
org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object 'scripts.LibraryContext@6a28ffa4'
with class 'scripts.LibraryContext' to class 'scripts.Factory$Binder'
	at scripts.Factory$Binder.bindStringFunction(CategoryTransform.groovy:18)
	at scripts.Factory$_create_closure1.doCall(CategoryTransform.groovy:10)
	at scripts.Factory$_create_closure1.doCall(CategoryTransform.groovy)
	at scripts.Factory.create(CategoryTransform.groovy:9)
	at scripts.Factory$create.call(Unknown Source)
	at scripts.CategoryTransform.run(CategoryTransform.groovy:42)
{code}

{code:java}
package scripts

class Factory {

  private Factory() {}

  static LibraryContext create() {
    LibraryContext context = new LibraryContext()
    use (Binder) {
      context.bindStringFunction('', { String[] strings -> '' })
    }
    return context
  }

  @Category(LibraryContext)
  private static class Binder {
    void bindStringFunction(String name, java.util.function.Function<String[], String>
func) {
      def stringFunction = new LibarayFunction(name, 0) {
        @Override
        String compute(String... args) {
            func.apply(args)
        }
      }

      this.bind(name, stringFunction)
    }
  }
}

class LibraryContext {
  void bind(String name, Object value) {
  }
}

abstract class LibarayFunction {
  LibarayFunction(String name, int argc) {
  }

  abstract String compute(String... argv);
}

Factory.create()
{code}



> Anonymous inner class results in cast exception with @Category applied
> ----------------------------------------------------------------------
>
>                 Key: GROOVY-8433
>                 URL: https://issues.apache.org/jira/browse/GROOVY-8433
>             Project: Groovy
>          Issue Type: Bug
>            Reporter: Eric Milles
>
> In working with a library that required extension of an SAM type to add a function binding,
I thought of using {{@Category}} to soften the integration.  What I found is that the implicit
{{this}} parameter that is passed to the constructor of an anon. inner class is being transformed
from the containing class to the category class due to the application of the {{@Category}}
transform.
> Below I have boiled it down to the fewest moving parts I can.  {{LibraryContext}} is
the type that needs functions bound to it and the interface for doing so is {{LibraryFunction}}
which requires constructor params so I cannot use SAM Closure coercion.  My first take was
to create {{Factory.Binder}} to get the details out of the way.  That resulted in the cast
exception below.  When I converted {{Binder}} to define static methods with a first param
of {{LibraryContext}} all is well.
> So I thought I would raise the issue that anon. inners and {{@Category}} are not currently
compatible.
> {code}
> Caught: org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object
'scripts.LibraryContext@6a28ffa4' with class 'scripts.LibraryContext' to class 'scripts.Factory$Binder'
> org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object 'scripts.LibraryContext@6a28ffa4'
with class 'scripts.LibraryContext' to class 'scripts.Factory$Binder'
> 	at scripts.Factory$Binder.bindStringFunction(CategoryTransform.groovy:18)
> 	at scripts.Factory$_create_closure1.doCall(CategoryTransform.groovy:10)
> 	at scripts.Factory$_create_closure1.doCall(CategoryTransform.groovy)
> 	at scripts.Factory.create(CategoryTransform.groovy:9)
> 	at scripts.Factory$create.call(Unknown Source)
> 	at scripts.CategoryTransform.run(CategoryTransform.groovy:42)
> {code}
> {code:java}
> package scripts
> class Factory {
>   private Factory() {}
>   static LibraryContext create() {
>     LibraryContext context = new LibraryContext()
>     use (Binder) {
>       context.bindStringFunction('', { String[] strings -> '' })
>     }
>     return context
>   }
>   @Category(LibraryContext)
>   private static class Binder {
>     void bindStringFunction(String name, java.util.function.Function<String[], String>
func) {
>       def stringFunction = new LibarayFunction(name, 0) { // cast exception here due
to implicit first param of "this"
>         @Override
>         String compute(String... args) {
>             func.apply(args)
>         }
>       }
>       this.bind(name, stringFunction)
>     }
>   }
> }
> class LibraryContext {
>   void bind(String name, Object value) {
>   }
> }
> abstract class LibarayFunction {
>   LibarayFunction(String name, int argc) {
>   }
>   abstract String compute(String... argv);
> }
> Factory.create()
> {code}



--
This message was sent by Atlassian JIRA
(v6.4.14#64029)

Mime
View raw message