在我的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方法中可用。有没有办法在不创建第二个自定义构造函数的情况下实现这一目标?
答案 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.
*/
}
}