Groovy
  1. Groovy
  2. GROOVY-2565

Exception with inheritance and private method calls from a closure

    Details

    • Type: Bug Bug
    • Status: Closed
    • Priority: Major Major
    • Resolution: Duplicate
    • Affects Version/s: 1.5.2
    • Fix Version/s: None
    • Component/s: None
    • Labels:
      None

      Description

      The test 'testClosureCallWithPrivateMethod' fails with Groovy 1.5.1 and 1.5.2 (I don't know about the other versions). It should not fail.

      class Parent {
          void publicMethod1() {
              privateMethod()
          }
      
          void publicMethod2() {
              [''].each { privateMethod()}
          }
      
          void publicMethod3() {
              [''].each { protectedMethod()} 
          }
      
          private void privateMethod() {}
      
          protected void protectedMethod() {}
      }
      
      class Child extends Parent {}
      
      class ClosureMethodCallTest extends GroovyTestCase {
          void testDirectCall() {
              // No exceptions means the test passes
              new Child().publicMethod1()
          }
          
          void testClosureCallWithPrivateMethod() {
              // No exceptions means the test passes
              new Child().publicMethod2()
          }
      
          void testClosureCallWithProtectedMethod() {
              // No exceptions means the test passes
              new Child().publicMethod3()
          }
      }
      

        Issue Links

          Activity

          Hide
          Jochen Theodorou added a comment -

          this issue is duplicating GROOVY-3073

          Show
          Jochen Theodorou added a comment - this issue is duplicating GROOVY-3073
          Hide
          Roshan Dawrani added a comment -

          Hi,
          I looked into this issue and it is not working in 1.5.8 because its handling of missing method is different from 1.6.

          In 1.5.8, MetaClassImpl -> invokeMissingMethod() simply throws MissingMethodExceptionNoStack if no missingMethod exception has been explicitly provided by user.

          In 1.6, MetaClassImpl -> invokeMissingMethod() does a lot more before deciding to throw the MissingMethodExceptionNoStack. One of the things it does is that it looks for the called methods up the class hierarchy and this is what is making the difference.

          In the code below, the closure's owner is Child object but Child class itself does not define privateMethod. Since 1.6 invokeMissingMethod() also checks up the hierarchy, it is successful. And since 1.5 invokeMissingMethod() doesn't do it, it fails to lookup privateMethod.

          I will try working on a patch for 1.5.8 to introduce this check up the hierarchy in 1.5.8 as well. Please let me know if anyone sees any issues with that.

          new Child().publicMethod2()
          
          class Parent {
              void publicMethod2() {
                  def cl = { privateMethod()}
                  cl()
              }
              private void privateMethod() {println "success"}
          }
          
          class Child extends Parent {}
          

          rgds,
          Roshan

          Show
          Roshan Dawrani added a comment - Hi, I looked into this issue and it is not working in 1.5.8 because its handling of missing method is different from 1.6. In 1.5.8, MetaClassImpl -> invokeMissingMethod() simply throws MissingMethodExceptionNoStack if no missingMethod exception has been explicitly provided by user. In 1.6, MetaClassImpl -> invokeMissingMethod() does a lot more before deciding to throw the MissingMethodExceptionNoStack. One of the things it does is that it looks for the called methods up the class hierarchy and this is what is making the difference. In the code below, the closure's owner is Child object but Child class itself does not define privateMethod. Since 1.6 invokeMissingMethod() also checks up the hierarchy, it is successful. And since 1.5 invokeMissingMethod() doesn't do it, it fails to lookup privateMethod. I will try working on a patch for 1.5.8 to introduce this check up the hierarchy in 1.5.8 as well. Please let me know if anyone sees any issues with that. new Child().publicMethod2() class Parent { void publicMethod2() { def cl = { privateMethod()} cl() } private void privateMethod() {println "success" } } class Child extends Parent {} rgds, Roshan
          Hide
          Guillaume Delcroix added a comment -

          Already working in 1.6, not yet in 1.5.x.

          Show
          Guillaume Delcroix added a comment - Already working in 1.6, not yet in 1.5.x.
          Hide
          Jochen Theodorou added a comment -

          I can confirm this is no issue in 1.6

          Show
          Jochen Theodorou added a comment - I can confirm this is no issue in 1.6

            People

            • Assignee:
              Jochen Theodorou
              Reporter:
              Hans Dockter
            • Votes:
              0 Vote for this issue
              Watchers:
              0 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved:

                Development