Marcin Zajączkowski
Marcin Zajączkowski

Reputation: 4126

Setting property value in Groovy using two different setters

I would like to allow user to set a BigDecimal property in my class using both BigDecimal and String (for backward compatibility reasons).

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

It tried to use two setter with different parameter types:

class PitestPluginExtension {
    BigDecimal timeoutFactor

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

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

but Groovy fails with:

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

If the setters are called directly everything work fine, but this is a Gradle plugin and people used to use property assignments.

Is it possible to tell Groovy (1.8.6) to use different input types on a property assignment (preferably without using Groovy meta programming)?

Upvotes: 0

Views: 733

Answers (2)

Marcin Zajączkowski
Marcin Zajączkowski

Reputation: 4126

The following solution (hinted by @Don's answer!) seems to work because 1.21 as BigDecimal is losslessly converted to String and used in the setter. Later it can be get as 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

Upvotes: 0

Dónal
Dónal

Reputation: 187529

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

Upvotes: 2

Related Questions