0

我正在尝试使用元类访问实例的方法,但我收到该属性不存在的错误。有没有办法访问在另一个类中声明的类的属性。

这是一个人为的例子:

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

有没有办法访问df.ftgetDf().getFt()使用 Groovy 的元类方法?

提前致谢

4

2 回答 2

1

doAction(rex.getDF(), "ft") 应该可以工作,尽管这不是您所追求的。

你也可以在引号中建立任何你想要的东西,所以我认为是这样的:

"${doAction(rex, df.ft)}" 会起作用。

我相信您遇到的具体问题是“$action”语法明确地引用了您正在调用的类的属性,因此您的组合内容似乎不起作用。

我相信如果 dfs="df" 和 fts="ft" 那么 rex."$dfs"."$fts" 可能有效,但你必须调整你的 doAction 方法。

- - 顺便一提。

如果您只是想为自己或一个非常小的团队编写代码,那么您想要的解决方案类型很好,但这并不是解决这个问题的真正“好”方法,总的来说我会尝试找到更好的模式。起初看起来很整洁,但是:

  • A) 不明显
  • B)它会使您的工具功能降低(要求 eclipse 找到“ft”方法的所有用途——它会错过这个)
  • C)它将检查移动到可以在编译时完成的运行时
  • D)由于上述所有原因以及更多原因,可维护性较差。

    如果我为代码执行此操作,我必须长期处理,我会先尝试在纯 Java 中解决它,然后将该解决方案优化为 groovy。

    最明显的方式是你有一个所有动物都实现的eat() 和bark() 接口——你的代码通常可以选择直接调用哪一个。

    如果您无法确定您希望直接从代码中调用什么(例如,如果您希望用户键入“bark”),我会使用命令模式——一个“命令”对象用于吃,一个不同的 oen 用于树皮每个都可以通过接口连接到任何动物。

  • 于 2013-09-04T18:44:06.040 回答
    1

    我认为您不能.使用该符号访问字符串名称中带有 a 的任何内容。你可以做到这一点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>
    
    于 2013-09-04T18:58:10.053 回答