Результат замены / переопределения беспараметрического метода, не переданного в конструктор

Я пытаюсь изменить поведение конструктора класса groovy, заменив метод в этом классе, который используется для установки свойства, но свойства не устанавливаются с ожидаемыми значениями.

class TestClass {

    def noParam
    def withParam

    TestClass() {
        noParam = noParam()
        withParam = withParam('second test')
    }

    def noParam() {
        return 'first test'
    }

    def withParam(param) {
        return param
    }

}

TestClass.metaClass.withParam =  { param -> 'pass' }
TestClass.metaClass.noParam = {-> 'pass' }

def test = new TestClass()

assert test.withParam('dummy') == 'pass' //passes
assert test.withParam == 'pass' // fails
assert test.noParam() == 'pass' // passes
assert test.noParam == 'pass' // fails

1 ответ

Решение

Groovy не использует переопределения метакласса в конструкторе TestClass, когда выполняет noParam а также withParam методы. На самом деле, если вы введете параметр в вашем withParam Метод 2-го утверждения также не удастся.

class TestClass {

    def noParam
    def withParam

    TestClass() {
        noParam = noParam()
        withParam = withParam('second test')
        println "in the constructor: noParam = $noParam, withParam = $withParam"
    }

    def noParam() {
        return 'first test'
    }

    def withParam(String param) {
        return param
    }
}

TestClass.metaClass.withParam = { String param -> 'pass' }
TestClass.metaClass.noParam = {-> 'pass' }

def test = new TestClass()

assert test.withParam('dummy') == 'pass'
assert test.withParam  == 'pass' // this fails now too!
assert test.noParam() == 'pass'
assert test.noParam == 'pass' // this fails

Вот вывод: in the constructor: noParam = first test, withParam = second test

test.withParam а также test.noParam на самом деле звонят test.getWithParam() а также test.getNoParam() - они возвращают значения свойств, установленные в конструкторе.

test.withParam('dummy') а также test.noParam() Вызываете ваш метод метакласса и возвращаете "pass".

Что касается того, почему groovy не использует метод метакласса в вашем конструкторе, я не уверен... Я не смог найти ничего в документации метакласса...

Может быть, вы могли бы использовать вместо этого статические методы?

class TestClass {

    def noParam
    def withParam

    TestClass() {
        noParam = TestClass.noParam()
        withParam = TestClass.withParam('second test')
        println "in the constructor: noParam = $noParam, withParam = $withParam"
    }

    static def noParam() {
        return 'first test'
    }

    static def withParam(String param) {
        return param
    }
}

TestClass.metaClass.'static'.withParam = { String param -> 'pass' }
TestClass.metaClass.'static'.noParam = {-> 'pass' }

def test = new TestClass()

assert test.withParam('dummy') == 'pass'
assert test.withParam  == 'pass' // passes!
assert test.noParam() == 'pass'
assert test.noParam == 'pass' // passes!

Вот вывод: in the constructor: noParam = pass, withParam = pass

Другие вопросы по тегам