Ken Pino
Ken Pino

Reputation: 31

How to create method names dynamically in groovy

At the moment I have the following code:

class SampleFixture {

    static aFixtureWithCodeAA() {
        fixtureAA()
    }

    static aFixtureWithCodeBB() {
        fixtureBB()
    }

    static aFixtureWithCodeCC() {
        fixtureCC()
    }
}

I'd like to transform this into something like

class SampleFixture {

    static aFixture(code) {
        fixture[code]()
    }
}

I have another class where fixtureAA, fixtureBB and fixtureCC are defined. So the code values are predefined. I want the method fixture[code] to be build at run-time rather than having a method for every single fixture.

How can I do this?

EDIT: I've been reading this http://groovy-lang.org/metaprogramming.html#_dynamic_method_names and it looks like what I want to do but I can't seem to get it to work.

Just to clarify: after reading this article, what I would like to end up with is a method with a baseName+varSufix as in "fixture${code}"(). Ideally I would end up with something like:

class SampleFixture {

    static aFixture(code) {
        MyClass."fixture{code}"()
    }
}

So I'd have a different method name depending on the code I am passing.

Upvotes: 2

Views: 1115

Answers (2)

tim_yates
tim_yates

Reputation: 171154

Do you just mean:

class MyClass {
    static fixtureAA() { "oooh, aa" }
    static fixtureBB() { "cool, bb" }
    static fixtureCC() { "wow,  cc" }
}

class MyFixture {
    def call(code) {
        MyClass."fixture$code"()
    }
}

println new MyFixture().call('BB')

(you were so close)

Or, you could do something like:

class MyClass {
    static fixtureAA() { "oooh, aa" }
    static fixtureBB() { "cool, bb" }
    static fixtureCC() { "wow,  cc" }
}

class MyFixture {
    def methodMissing(String name, args) {
        try {
            MyClass."fixture$name"()
        }
        catch(e) {
            "No idea how to $name"
        }
    }
}

assert "oooh, aa" == new MyFixture().AA()
assert "cool, bb" == new MyFixture().BB()
assert "wow,  cc" == new MyFixture().CC()
assert "No idea how to DD" == new MyFixture().DD()

Upvotes: 2

Will
Will

Reputation: 14549

You can implement a method called invokeMethod(String method, args) and parse the code from the method argument:

class SampleFixture {

    def fixture = [
        AA: { "code aa" },
        BB: { "code bb" },
        CC: { "code cc" },
    ]

    def invokeMethod(String method, args) {
        def code = method - "aFixtureWithCode"
        fixture[code]()
    }
}


f = new SampleFixture()

assert f.aFixtureWithCodeAA() == "code aa"
assert f.aFixtureWithCodeBB() == "code bb"
assert f.aFixtureWithCodeCC() == "code cc"

UPDATE: here's a solution using a second class to redirect the method call to another class

class Fixture {
    def fixtureAA() { "code aa" }
    def fixtureBB() { "code bb" }
    def fixtureCC() { "code cc" }
}

class SampleFixture {}

SampleFixture.metaClass.static.invokeMethod = { String method, args ->
    def code = method - "aFixtureWithCode"
    new Fixture()."fixture${code}"()
}


assert SampleFixture.aFixtureWithCodeAA() == "code aa"
assert SampleFixture.aFixtureWithCodeBB() == "code bb"
assert SampleFixture.aFixtureWithCodeCC() == "code cc"

Upvotes: 1

Related Questions