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

static methods added through metaClass can't have default values for parameters

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Closed
    • Major
    • Resolution: Fixed
    • 1.6
    • 1.6.1, 1.7-beta-1
    • class generator
    • None
    • This is seen in groovy 1.6.0 on Leopard:

      % groovy -version
      Groovy Version: 1.6.0 JVM: 1.6.0_07

    Description

      I'm running into an issue with Groovy 1.6 trying to add a static method to the metaClass where the closure for the method has some parameters with default values.

      When trying to call the method and not supplying some default values, it doesn't find the newly added method and instead throws a MissingMethodException.

      Default parameters work fine with a class where the static method is defined directly on the class, both through using a closure as well as a normal method definition:

      class MyClass {
      def testInstance(first = "foo")

      { return "$first" }

      static testStatic(first = "foo") { return "$first" }

      static testStaticClosure =

      { first = "foo" -> return "$first" }

      static testStaticTwoParms(first = "foo", second = "bar")

      { return "$first - $second" }

      static testStaticTwoParmsClosure =

      { first = "foo", second = "bar" -> return "$first - $second" }


      }

      assert "foo" == new MyClass().testInstance()
      assert "foo" == MyClass.testStatic()
      assert "foo" == MyClass.testStaticClosure()
      assert "foo - bar" == MyClass.testStaticTwoParms()
      assert "foo - bar" == MyClass.testStaticTwoParmsClosure()

      Using the metaClass, it works fine to add instance methods with single or multiple defaulted values:

      String.metaClass.testInstance =

      { first = "foo" -> return "$first" }

      assert "foo" == "".testInstance() // works as expected

      String.metaClass.testInstanceTwoParams = { first = "foo", second = "bar" -> return "$first - $second" }

      assert "foo - bar" == "".testInstanceTwoParams() // also works as expected


      But when a static method is added to a class via the metaClass, a single default parameter doesn't use the default value for the paramter, it has a null value:

      String.metaClass.'static'.testStatic = { first = "foo" -> return "$first" }

      assert "qux" == "".testStatic("qux") // works if you specify a parameter
      assert "foo" == "".testStatic() // Fails! "foo" isn't returned, instead it returns a null value

      It gets weirder if you try to specify two defaulted parameters on the static closure. Instead of just not assigning values to the parameters, it doesn't even find the method and throws a MissingMethodException:

      String.metaClass.'static'.testStaticTwoParams =

      { first = "foo", second = "bar" -> return "$first - $second" }

      assert "baz - qux" == "".testStaticTwoParams("baz", "qux") // works if you specify parameters
      assert "baz - bar" == "".testStaticTwoParams("baz") // Fails with MissingMethodException!
      assert "foo - bar" == "".testStaticTwoParams() // Fails with MissingMethodException! Not finding method with defaulted pararameters

      This is seen in groovy 1.6.0:

      % groovy -version
      Groovy Version: 1.6.0 JVM: 1.6.0_07

      I also tested this code against 1.5.7 and it exhibits the same behavior, but is also broken for metaClass added instance methods with defaulted values, which work in 1.6. Hopefully whatever was changed in 1.6 to fix that can also be applied to class level static methods.

      Attachments

        1. 3405_v16x.txt
          4 kB
          Roshan Dawrani

        Activity

          People

            roshandawrani Roshan Dawrani
            tednaleid Ted Naleid
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved: