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

Accessing private methods from public ones using categories and inheritance causes MissingMethodException

    XMLWordPrintableJSON

    Details

    • Type: Bug
    • Status: Closed
    • Priority: Major
    • Resolution: Fixed
    • Affects Version/s: 1.8.9, 2.0.8, 2.1.6, 2.4.0-rc-1
    • Fix Version/s: 2.5.0-alpha-1
    • Component/s: groovy-runtime
    • Labels:

      Description

      Private methods cannot be accessed from public ones when categories are used, and inheritance is involved.

      Consider this code:

      class A {
          private foo(a) { 1 }
          def baz() { foo() }
      }
      
      class B extends A {}
      
      class C {}
      
      use(C) {
          new B().baz()
      }
      

      Calling baz() fails with the MissingMethodException. Here is the error message and the partial stacktrace:

      groovy.lang.MissingMethodException: No signature of method: B.foo() is applicable for argument types: () values: []
      Possible solutions: baz(), any(), find(), use([Ljava.lang.Object;), find(groovy.lang.Closure), is(java.lang.Object)
      	at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.unwrap(ScriptBytecodeAdapter.java:55)
      	at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.callCurrent(PogoMetaClassSite.java:78)
      	at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:49)
      	at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:133)
      	at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:137)
      	at A.baz(ConsoleScript0:3)
      	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
      	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
      	at java.lang.reflect.Method.invoke(Method.java:606)
      	at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)
      	at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:233)
      	at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1085)
      	at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:909)
      	at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.call(PogoMetaClassSite.java:39)
      	at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:45)
      	at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:108)
      	at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:112)
      	at ConsoleScript0$_run_closure1.doCall(ConsoleScript0:11)
      	at ConsoleScript0$_run_closure1.doCall(ConsoleScript0)
      	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
      	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
      	at java.lang.reflect.Method.invoke(Method.java:606)
      	at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)
      	at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:233)
      	at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:272)
      	at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:909)
      	at groovy.lang.Closure.call(Closure.java:411)
      	at groovy.lang.Closure.call(Closure.java:405)
      	at org.codehaus.groovy.runtime.GroovyCategorySupport$ThreadCategoryInfo.use(GroovyCategorySupport.java:109)
      	at org.codehaus.groovy.runtime.GroovyCategorySupport$ThreadCategoryInfo.access$400(GroovyCategorySupport.java:65)
      	at org.codehaus.groovy.runtime.GroovyCategorySupport.use(GroovyCategorySupport.java:249)
      	at org.codehaus.groovy.runtime.DefaultGroovyMethods.use(DefaultGroovyMethods.java:385)
      	at org.codehaus.groovy.runtime.dgm$594.invoke(Unknown Source)
      	at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite$PogoMetaMethodSiteNoUnwrapNoCoerce.invoke(PogoMetaMethodSite.java:313)
      	at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite.callCurrent(PogoMetaMethodSite.java:52)
      	at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:49)
      	at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:133)
      	at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:145)
      	at ConsoleScript0.run(ConsoleScript0:10)
      ...
      

      Without using categories, everything is fine:

      //use(C) {
          assert new B().baz() == 1
      //}
      

      as is without inheritance:

      use(C) {
          assert new A().baz() == 1
      }
      

      Not using private modifier also helps:

      class A {
          protected foo(a) { 1 }
          def baz() { foo() }
      }
      
      class B extends A {}
      
      class C {}
      
      use(C) {
          assert new B().baz() == 1
      }
      

        Attachments

          Activity

            People

            • Assignee:
              blackdrag Jochen Theodorou
              Reporter:
              dsrkoc Dinko Srkoc
            • Votes:
              1 Vote for this issue
              Watchers:
              4 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved: