为什么我不能将我的地图强制转换为IStringHolder的构造函数?
当我运行Example.main
时$('#btnSubmit').on('click', function() {
alert('test');
var propertyAdd = $('#additions_info_0_0').val();
var mobile = $('#additions_info_0_1').val();
var StringContent = '<p>I am thrilled to share my new listing with you at ' + propertyAdd + '. To find out more about this exciting property, or to hear about one of the many others currently on the market, call me to set up an appointment at ' + mobile + ' I would be happy to answer your questions, discuss your needs, and set you on track to achieving your real estate goals. Looking forward to hearing from you soon!</p>';
$('#contentDiv').html(StringContent);
});
我收到以下异常
interface IStringHolder {
String getString()
}
class StringHolder implements IStringHolder {
String string
StringHolder(string) {
this.string = string
}
@Override
String getString() {
return string
}
}
class Example {
public static void main(String[] args) {
doSomething([string:"hey"] as IStringHolder)
}
static void doSomething(IStringHolder stringHolder) {
println stringHolder.getString()
}
}
为什么例外来自Example.doSomething的第一行?
当我将地图强制转换为StringHolder时,它会起作用。发生了什么事?
答案 0 :(得分:2)
此代码存在以下问题:
doSomething([string:"hey"] as IStringHolder)
您尝试利用Groovy的语言功能称为显式构造函数强制,它在IStringHolder
类中查找可以使用您提供的参数调用的构造函数
在这种情况下,Groovy将在IStringHolder
类中查找它可以调用以实例化它的无参数构造函数,然后它将查找一个setter setString(String str)
并使用{{ 1}}你提供了。
您看到"hey"
的原因是因为UnsupportedOperationException
中没有构造函数可以调用,因为它不是实现。
将类型强制转换为IStringHolder
确实有效,但可能并不像您期望的那样。如果你只提供了as StringHolder
,而不是"hey"
,它就会完成你所期望的和我上面详述的内容。这是因为映射被解释为Named Argument Constructor,这会导致Groovy使用它可以找到的唯一构造函数来实例化对象,将string:"hey"
传递给它,然后调用合成的null
方法一旦它被构建,就setString(String str)
。虽然这会产生您正在寻找的结果,但它会以非直观的方式实现。
显式构造函数强制
"hey"
在这里,Groovy将寻找一个构造函数,该构造函数采用类型StringHolder stringHolderImpl = [ "hey" ] as StringHolder
的一个arg并将值String
传递给它。
隐式构造函数强制
"hey"
这与上面相同,除了Groovy使用左侧类型来确定右侧可能是什么,在继续查找构造函数之前等等。
我不建议这只是因为它让Groovy假设太多,而像Intellij这样的IDE会抱怨这种语法。
明确关闭强制
如果您坚持不使用实现类StringHolder stringHolder = [ "hey" ]
,可以通过以下方式在运行时创建实现:
StringHolder
这会创建一个满足IStringHolder stringHolderImpl = { getString: "hey" } as IStringHolder
契约的闭包,因此可以很容易地将其转换为它的实现。
隐含关闭强制
IStringHolder
我再也不推荐这种风格,但它有效。
由于显式特性,我是显式构造函数强制的粉丝,因为它不需要创建闭包的开销。当我需要一个只需要在运行时存在的类的实现时,我将不时使用显式闭包强制。
什么是最好的选择?你必须自己确定一下!