如何覆盖';地图';Grails域类中的构造函数?

如何覆盖';地图';Grails域类中的构造函数?,grails,groovy,gorm,Grails,Groovy,Gorm,我需要在创建域类的新实例时执行一些初始化 class ActivationToken { String foo String bar } 执行此操作时,我希望通过ActivationToken内的代码初始化bar: def tok = new ActivationToken(foo:'a') 我看不出如何“重写”构造函数来实现这一点。我知道在本例中,我可以添加一个普通构造函数,但这只是一个简单的示例。映射构造函数来自Groovy,在本例中不是Grails。我做了一些实验,这就

我需要在创建域类的新实例时执行一些初始化

class ActivationToken {
    String foo
    String bar
}
执行此操作时,我希望通过ActivationToken内的代码初始化bar:

def tok = new ActivationToken(foo:'a')

我看不出如何“重写”构造函数来实现这一点。我知道在本例中,我可以添加一个普通构造函数,但这只是一个简单的示例。

映射构造函数来自Groovy,在本例中不是Grails。我做了一些实验,这就是我想到的:

class Foo {
    String name = "bob"
    int num = 0

    public Foo() {
        this([:])
    }

    public Foo(Map map) {
        map?.each { k, v -> this[k] = v }
        name = name.toUpperCase()
    }

    public String toString() {
        "$name=$num"
    }
}

assert 'BOB=0' == new Foo().toString()
assert 'JOE=32' == new Foo(name:"joe", num: 32).toString()
基本上,如果您需要在构造之后处理属性,则必须手动重写构造函数

或者,您可以覆盖单个设置器,这通常更干净、更安全:

class Foo {
    String name = "bob"
    int num = 0

    public void setName(n) {   
        name = n.toUpperCase()
    }

    public String toString() {
        "$name=$num"
    }
}

assert 'bob=0' == new Foo().toString()
assert 'JOE=32' == new Foo(name:"joe", num: 32).toString()

请注意,默认值不会被处理,但在大多数情况下应该可以。

上述解决方案也适用于根据web请求中的参数初始化对象的情况,例如,您希望忽略无关值,捕获缺少的属性异常

public Foo(Map map) {
    try {
        map?.each { k, v -> this[k] = v }
    }
    catch(Exception e){
    }
}

您不能为域上的
bar
设置默认值吗?我需要设置的值计算起来很昂贵,因此我不希望Hibernate等人创建的每个默认实例都会产生此成本空映射的构造函数给我一个StackOverflowException:(我的映射构造函数甚至没有被调用……grails只调用默认构造函数。