【问题标题】:How can I override the 'map' constructor in a Grails domain class?如何覆盖 Grails 域类中的“地图”构造函数?
【发布时间】:2011-09-13 10:35:46
【问题描述】:

当我的域类的新实例被创建时,我需要执行一些初始化。

class ActivationToken {
    String foo
    String bar
}

当我这样做时,我希望 bar 由 ActivationToken 中的代码初始化:

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

我看不到如何“覆盖”“构造函数”来实现这一点。我知道在这种情况下我可以添加一个普通的构造函数,但这只是一个简单的例子。

【问题讨论】:

  • 你不能在域上为bar设置默认值吗?
  • 我需要设置的值计算起来很昂贵,所以我不希望 Hibernate 等创建的每个默认实例都产生这个成本

标签: grails groovy grails-orm


【解决方案1】:

地图构造函数来自 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()

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

【讨论】:

  • 带有空地图的构造函数给了我一个 StackOverflowException :(
  • 我的地图构造函数甚至没有被调用... grails 只是调用默认构造函数。
  • 运行 rails 3.3.11。此解决方案不起作用
【解决方案2】:

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-04-11
    • 1970-01-01
    • 1970-01-01
    • 2015-02-01
    • 1970-01-01
    • 2021-01-17
    • 1970-01-01
    相关资源
    最近更新 更多