Метод перегрузки в заводной - PullRequest
3 голосов
/ 22 мая 2010

Я пытаюсь воспользоваться удобством синтаксиса сценариев groovy для назначения свойств, но у меня возникают проблемы с конкретным случаем.Я, должно быть, здесь упускаю что-то простое.Я определяю класс A, B, C следующим образом:

class A {

    A() {
        println "Constructed class A!"
    }

}

class B {

    B() {
        println "Constructed class B!"
    }

}

class C {

    private member 

    C() {
        println "Constructed class C!"
    }

    def setMember(A a) {

        println "Called setMember(A)!"
        member = a

    }

    def setMember(B b) {

        println "Called setMember(B)!"
        member = b

    }

}

И затем попробуйте выполнить следующие вызовы в скрипте:

c = new C()

c.setMember(new A()) // works
c.member = new A()   // works

c.setMember(new B()) // works
c.member = new B()   // doesn't work!

Последнее назначение приводит к ошибке: «Невозможно привестиобъект класса B для класса A ". Почему он не вызывает надлежащий метод setMember для класса B, как это делается для класса A?

1 Ответ

2 голосов
/ 23 мая 2010

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

Вы также можете прочитать Расширенные комментарии Pyrasun о недостатках обработки свойств Groovy.

Если вы хотите обойти это (неправильное) поведение, вам нужно напрямую вызвать сеттер, так как Groovy поддерживает проверку типов для вызовов методов. В качестве альтернативы вы также можете получить доступ к полю напрямую без установщика, используя

c.@member = new B()

или вы самостоятельно проверяете тип в одном методе установки:

def setMember(def param) {
  if (param instanceof A) println "Called setMember(A)!"
  if (param instanceof B) println "Called setMember(B)!"

  member = param
}
...