Groovy 中的惰性映射值

Lazy Map Values in Groovy

所以在 groovy 中你可以定义一个字符串,每次读取它的值时都会延迟检索它的值。

System.setProperty('foo', 'bar')

def getMyValue = {
  return System.getProperty('foo')
}

def myData = [
  value1: "${ getMyValue() }",
  vaule2: "${ -> getMyValue() }",
]

System.setProperty('foo', 'bam')
println "${myData}"

System.setProperty('foo', 'baz')
println "${myData}"

当 运行 这产生

[value1:bar, vaule2:bam]
[value1:bar, vaule2:baz]

这对于字符串值来说非常好

我想知道是否可以对数字类型做类似的事情

def myData = [
   myInt: { -> Integer.valueOf(System.getProperty('somePropThatIsSetDownStream')) },
]

或者如果有办法覆盖地图上的 get 方法,以便在执行 get 时我可以执行一个闭包,t运行s 形成 myData.myInt

的值
def valueTransformer = { key, map ->
    if(map[key] instanceOf Closure) {
      return map[key].call()
    }
    return map[key]
}

有没有可能有一个闭包来覆盖调用 myData.myInt 时发生的逻辑?

这取决于您想要实现的语法,但可能有很多解决方案。

我建议实现 Lazy 闭包 class 其中 toString 将调用闭包

@groovy.transform.CompileStatic
class Lazy extends Closure{
    @Delegate private Closure closure
    Lazy(Closure c){ 
        super(c.getOwner(), c.getThisObject())
        this.closure=c 
    }
    static Lazy of(Closure c){ new Lazy(c) }
    Object doCall(){ closure.call() }
    String toString(){ closure.call() as String }
}


def myData = [
   myInt: Lazy.of{ System.currentTimeMillis() },
]

//different printouts
println myData.myInt   //toString called
Thread.sleep(100)
println myData.myInt() //returns the value (not string)
Thread.sleep(100)
println myData

结果:

1576168290790
1576168290901
[myInt:1576168291003]