【问题标题】:Setting property value in Groovy using two different setters使用两个不同的 setter 在 Groovy 中设置属性值
【发布时间】:2014-04-16 04:51:59
【问题描述】:

我想允许用户使用BigDecimalString 在我的类中设置BigDecimal 属性(出于向后兼容性的原因)。

extension.timeoutFactor = 1.81
extension.timeoutFactor = "2.12"

它尝试使用两个具有不同参数类型的setter:

class PitestPluginExtension {
    BigDecimal timeoutFactor

    void setTimeoutFactor(BigDecimal timeoutFactor) {
        this.timeoutFactor = timeoutFactor
    }

    @Deprecated
    void setTimeoutFactor(String timeoutFactor) {
        //display deprecation warning
        this.timeoutFactor = timeoutFactor.toBigDecimal()
    }
}

但是 Groovy 失败了:

org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object
    '2.12' with class 'java.lang.String' to class 'java.math.BigDecimal'

如果直接调用 setter,一切正常,但这是 Gradle plugin,人们习惯使用属性分配。

是否可以告诉 Groovy (1.8.6) 在属性分配上使用不同的输入类型(最好不使用 Groovy 元编程)?

【问题讨论】:

  • 为什么不用元编程?
  • @WillP,扩展类由 Gradle 管理(请参阅配置 example),并且在此类上执行的内部 Gradle 魔术可能(可能)存在一些问题。因此,我更喜欢使用“标准”方法的明确解决方案(例如具有不同参数类型的设置器 - 不幸的是,这不起作用)。然而,如果在 Groovy 中它不是“可能的”,那么使用元编程的(工作)解决方案也可以。

标签: groovy


【解决方案1】:
import java.math.*

class PitestPluginExtension {
    private BigDecimal timeoutFactor

    void setTimeoutFactor(timeoutFactor) {
        this.timeoutFactor = new BigDecimal(timeoutFactor)
    }

    def getTimeoutFactor() {
        this.timeoutFactor
    }
}

// ignore differences due to precision errors
void compareImprecisely(BigDecimal expected, BigDecimal actual) {
    BigDecimal roundedExpected = Math.round(expected * 100) / 100
    BigDecimal roundedActual = Math.round(actual * 100) / 100
    assert roundedExpected == roundedActual
}

def ppe = new PitestPluginExtension()

def expected = new BigDecimal('1.11')

// test assigning a string
ppe.timeoutFactor = '1.11'
compareImprecisely expected, ppe.timeoutFactor

// test assigning a BigDecimal
ppe.timeoutFactor = 1.11
compareImprecisely expected, ppe.timeoutFactor

【讨论】:

  • 不错的技巧,感谢您的回答。我不喜欢new BigDecimal(1.11) 执行BigDecimal(double val) 而通常1.11.class == java.math.BigDecimal。这迫使我在传递值之前对其进行舍入。不过你的想法暗示了我另一个solution
【解决方案2】:

以下解决方案(由@Don 的回答提示!)似乎有效,因为1.21 as BigDecimal 被无损转换为String 并在setter 中使用。稍后可以通过BigDecimal获取。

class PitestPluginExtension {
    BigDecimal timeoutFactor

    void setTimeoutFactor(String timeoutFactor) {
        this.timeoutFactor = new BigDecimal(timeoutFactor)
    }
}

def extension = new PitestPluginExtension()
extension.timeoutFactor = "1.81"
assert extension.timeoutFactor == 1.81
extension.timeoutFactor = 1.21
assert extension.timeoutFactor == 1.21

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-27
    • 2016-01-06
    • 2011-01-19
    • 2017-07-01
    • 2016-07-02
    • 1970-01-01
    相关资源
    最近更新 更多