Groovy: добавление методов к экземплярам и классам с помощью metaClass не работает? - PullRequest
0 голосов
/ 23 октября 2009

См. Код ниже. Старые экземпляры класса, созданные до добавления метода в класс с использованием metaClass, не должны понимать метод правильно? Оператор assert под комментарием 'PROBLEMATIC LINE' выполняется, когда я думаю, что это не должно быть, так как старый экземпляр parentDir не должен понимать сообщение blech ().

// derived from http://ssscripting.wordpress.com/2009/10/20/adding-methods-to-singular-objects-in-groovy/

// Adding a method to a single instance of a class

def thisDir = new File('.')

def parentDir = new File('..')

thisDir.metaClass.bla = { -> "bla: ${File.separator}" }

assert thisDir.bla() == "bla: ${File.separator}" : 'thisDir should understand how to respond to bla() message'

try {
    parentDir.bla()
    assert false : 'parentDir should NOT understand bla() message'
} catch (MissingMethodException mmex) {
    // do nothing : this is expected
}

// Adding a method to all instances of a class

File.metaClass.blech = { -> "blech: ${File.separator}" }

try {
    thisDir.blech()
    assert false : 'old instance thisDir should NOT understand blech() message'
} catch (MissingMethodException mmex) {
    // do nothing : this is expected
}

try {
    parentDir.blech()
    // PROBLEMATIC LINE BELOW - THE LINE IS EXECUTED WHEN
    // I THINK AN EXCEPTION SHOULD HAVE BEEN THROWN
    assert false : 'old instance parentDir should NOT understand blech() message'
} catch (MissingMethodException mmex) {
    // do nothing : this is expected
}

thisDir = new File('.')
parentDir = new File('..')

try {
    thisDir.bla()
    assert false : 'new instance thisDir should NOT understand bla() message'
} catch (MissingMethodException mmex) {
    // do nothing : this is expected
}

assert "blech: ${File.separator}" == thisDir.blech() : 'new instance thisDir should understand blech() message'
assert "blech: ${File.separator}" == parentDir.blech() : 'new instance parentDir should understand blech() message'

Ответы [ 3 ]

4 голосов
/ 25 октября 2009

старый экземпляр parentDir не должен понять сообщение blech ()

Это не так, как metaclass работает. Вы, очевидно, исходите из ОО-языка на основе прототипа (JavaScript?). Groovy не основан на прототипах. Изменения в классе влияют на все экземпляры класса, включая созданные до изменения.

0 голосов
/ 25 октября 2009

Линия:

parentDir.blech()

успешно выполняется после добавления blech () в File, как вы говорите. Но если это так, то почему бы не позвонить выше этого:

thisDir.blech()

работать (не выбрасывать исключение, которое он выбрасывает), поскольку это еще один экземпляр класса File, а blech () уже добавлен в File? Либо оба вызова должны потерпеть неудачу с MissingMethodException, либо оба должны работать. Глупо, что один работает, а другой нет.

0 голосов
/ 23 октября 2009

Скрипт завершает свое выполнение с Caught: java.lang.AssertionError: old instance parentDir should NOT understand blech() message. Expression: false at x.run(x.groovy:35) . Вы не ожидали, что метод blech сработает? Я не понимаю, почему нет, поскольку вы добавляете его в метакласс File, а не только в метакласс объекта.

...