groovy中的方法重载

groovy中的方法重载,groovy,overloading,Groovy,Overloading,我试图利用groovy脚本语法的便利性来分配属性,但在特定情况下遇到了问题。我一定错过了一些简单的东西。我将A类、B类和C类定义为: class A { A() { println "Constructed class A!" } } class B { B() { println "Constructed class B!" } } class C { private member C() {

我试图利用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。”“。为什么它不能像调用类A那样为类B调用适当的setMember方法?

使用点表示法调用属性的setter方法的快捷方式不进行类型检查。相反,它似乎使用具有给定名称的方法列表中的第一个条目并调用它

您还可以阅读关于Groovy属性处理缺点的扩展评论

如果要绕过此(mis)行为,必须直接调用setter,因为Groovy支持方法调用的类型检查。或者,也可以不使用setter直接访问字段

c.@member=new B()

或者,您可以使用单个setter方法自己进行类型检查:

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

  member = param
}

克里斯托夫的回答是正确的,但正确的方法是不要这样做!为不同的参数类型创建不同的方法,或者让这些类型实现一个公共接口。方法重载在最好的情况下是邪恶的,但对于Groovy更松散的类型,它是彻头彻尾的邪恶。