我正在尝试使用元类访问实例的方法,但是我得到了属性不存在的错误。有没有办法访问在另一个类中声明的类的属性。
这是一个人为的例子:
class DogFood {
def ft = 'food!'
def foodType() { ft}
}
class Dog {
def bark() { println "woof!" }
DogFood df = new DogFood()
def ft() { println df.foodType()}
def getDf() {
df
}
}
def doAction( animal, action ) {
animal."$action"()
}
def rex = new Dog()
println rex.df.ft //works
def barkString = "bark"
doAction( rex, barkString ) //works
doAction( rex, "df.ft") //doesn't work
doAction( rex, "getDf().ft") //does not work
有没有办法使用Groovy的元类方法访问df.ft
或getDf().getFt()
?
提前致谢
答案 0 :(得分:1)
doAction(rex.getDF(),“ft”)应该有效,尽管这不是你想要的。
你也可以在引号中构建你想要的东西,所以我想像:
“$ {doAction(rex,df.ft)}”会起作用。
我认为你遇到的具体问题是“$ action”语法引用了你要调用的类的属性,所以你的组合内容似乎不起作用。
我相信如果dfs =“df”和fts =“ft”那么rex。“$ dfs”。“$ fts”可能会有效,但你必须调整你的doAction方法..
---顺便说一句。
如果你只是想为自己或一个非常小的团队编写代码,那么你想要的解决方案类型很好,但这并不是一个解决这个问题的“好方法”,总的来说我试图找到一个更好的模式。起初看起来很整洁,但是:
如果我为代码执行此操作我必须长期处理,我会首先尝试用纯Java解决它,然后将该解决方案优化为groovy。
最明显的方法是你有一个所有动物实现的eat()和bark()界面 - 你的代码通常可以选择直接调用哪一个。
如果您无法直接从代码中确定要调用的内容(例如,如果您希望用户键入“bark”),我将使用命令模式 - 一个“命令”对象用于进食和不同树皮可以通过界面附着在任何动物身上。
答案 1 :(得分:1)
我认为您不能使用该表示法访问字符串名称中.
的任何内容。您可以使用Eval.x
来完成此操作。
def doAction( animal, action ) {
Eval.x(animal, 'x.' + action)
}
编辑:
另请注意,如果您正在执行用户输入,则此方法存在风险。您可以使用Eval
执行任意代码。例如,
groovy:000> foo = [bark: { println 'bark' }]
===> {bark=groovysh_evaluate$_run_closure1@db2e44d}
groovy:000> Eval.x(foo, 'x.bark()')
bark
===> null
groovy:000> Eval.x(foo, 'x.bark(); println "executing more code"')
bark
executing more code
groovy:000>