Uploaded image for project: 'Groovy'
  1. Groovy
  2. GROOVY-8433

Anonymous inner class results in cast exception with @Category applied

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Closed
    • Major
    • Resolution: Fixed
    • None
    • 2.5.16, 3.0.10, 4.0.0
    • None
    • None

    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.

      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)
      
      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()
      

      Attachments

        Activity

          People

            emilles Eric Milles
            emilles Eric Milles
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:

              Time Tracking

                Estimated:
                Original Estimate - Not Specified
                Not Specified
                Remaining:
                Remaining Estimate - 0h
                0h
                Logged:
                Time Spent - 40m
                40m