groovy:更改setter属性调用顺序

时间:2016-03-15 17:48:15

标签: groovy

在我的groovy课程中,我有3个属性:

class Story{
    @JsonUnwrapped
    Object collections;

    String dateformat;    

    @JsonUnwrapped
    Object  custom;    

    public String getDateformat(){
        println "getDateformat - ${dateformat}";
        return this.dateformat;
    }
    public void setDateformat(String str){
        this.dateformat = str; 
        println "setDateformat - ${dateformat}";
    }

    public void setCollections(Object obj)
    {
        println "setCollections";
    }
    public void setCustom(Object obj){
        println "setCustom: ${this.dateformat}";
    }
}

在类实例化时,自动调用setter是这个顺序:

setCustom: null
setCollections
setDateformat - yyyy/MM/dd HH:mm:ss.SSS Z
getDateformat - yyyy/MM/dd HH:mm:ss.SSS Z

无法重命名字段。我希望dateformat属性在setCustom setter方法中可用。有没有办法在不创建第二个自定义构造函数的情况下实现这一目标?

1 个答案:

答案 0 :(得分:2)

令我惊讶的是,是的!

它非常简单。我排除了JSON注释,因为它们无关紧要,但这是一个例子:

class Story{
    Object collections
    String dateformat
    Object  custom

    public String getDateformat(){
        println "getDateformat - ${dateformat}";
        return this.dateformat;
    }
    public void setDateformat(String str){
        this.dateformat = str; 
        println "setDateformat - ${dateformat}";
    }

    public void setCollections(Object obj)
    {
        println "setCollections";
    }
    public void setCustom(Object obj){
        println "setCustom: ${this.dateformat}";
    }
}

def s = new Story(collections: new Object(), dateformat: 'yyyy/MM/dd HH:mm:ss.SSS Z', custom: new Object())

输出如下:

setCollections
setDateformat - yyyy/MM/dd HH:mm:ss.SSS Z
setCustom: yyyy/MM/dd HH:mm:ss.SSS Z

它是如何工作的?

诀窍是使用正确顺序定义的属性调用基于Map-的构造函数。

Groovy提供的基于Map的默认构造函数实际上是由运行时处理的。更具体地说,MetaClassImpl。它首先使用无参数构造函数创建一个实例,然后设置Map中的每个属性。这里重要的是如何设置属性:

for (Iterator iter = map.entrySet().iterator(); iter.hasNext();) {
    Map.Entry entry = (Map.Entry) iter.next();
    String key = entry.getKey().toString();

    Object value = entry.getValue();
    setProperty(bean, key, value);
}

如您所见,它遍历Map中的键并应用每个键。在我的示例中使用构造函数语法时,您将声明一个Groovy Map文字,最终成为LinkedHashMap的实例。 LinkedHashMap保留定义键的顺序,允许您控制属性的设置顺序。

你应该这样做吗?

说完所有这些之后,对设置属性的顺序有如此不直观的依赖会使Story类非常脆弱。相反,您可以添加一个新方法,让我们调用它validate(),它将考虑属性的相互依赖性,并确保在使用实例之前一切都很好。

class Story{
    Object collections
    String dateformat
    Object custom

    boolean validate() {
        /*
         * Do whatever the hell you want with
         * dateformat and custom.
         * Return whether it's all good or not.
         * Or, throw an Exception.
         */
    }
}