https://kotlinlang.org logo
Title
j

Juan B

10/09/2020, 1:54 AM
Hi Everybody! .. I'm just doing my first steps in Kotlin after a long time using Groovy, so far I'm enjoying it. I have a question, probably simple but Im trying to get some traction. -> If I have an app which is using BigDecimal heavily, is there a way to avoid creating theBigDecimal explicitly when calling methods that expect a BigDecimal? (something like implicit transformation from integer to BigDecimal on the caller so you can call methods using just a integer) E.g. When instantiating this data class, I have to pass the salary as explicit integer:
val employeeRunData = EmployeeRunData(annualSalary = BigDecimal(120000))
Instead, I would like to do something like: <note there is not call to _BigDecimal(120000)_>
val employeeRunData = EmployeeRunData(annualSalary = 120000))
I would highlight that the annoyance is while writing unit test. Thank you all!
m

Milan Hruban

10/09/2020, 6:20 AM
there is no implicit conversion, but you can always do
fun EmployeeRunData(annualSalary: Int) = EmployeeRunData(annualSalary = BigDecimal(annualSalary))
m

Michael de Kaste

10/09/2020, 8:31 AM
secondary constructors are probably what you need:
fun main(){
    val constructWithBigDecimal = EmployeeRunData(BigDecimal.TEN)
    val constructWithNumber = EmployeeRunData(2341L)
}

data class EmployeeRunData(val annualSalary: BigDecimal) {
    constructor(annualSalary: Number) : this(BigDecimal(annualSalary.toString()))
}
This way, whenever you call the constructor of EmployeeRunData, it will set its annualSalary directly if you call it with a BigDecimal, otherwise it will call it with the constructor. If your problem is in writing unittests only, I suggest just making local functions
m

Martin

10/09/2020, 9:40 AM
previously, in another language, I used extension methods to make this a bit easier. So if
foo()
expects a BigDecimal, you could call it like
foo(<http://123.bd|123.bd>)
🤔 1
e

elizarov

10/09/2020, 4:26 PM
That’s what I’d recommend:
val <http://Int.bd|Int.bd> get() = toBigDecimal()
🤔 1
1
j

Juan B

10/13/2020, 5:52 AM
Thanks all for the answers. I’m trying to avoid secondary constructors because I want the production contract to be only with BigDecimal. I think that @Martin and @elizarov answers are what I’m looking for. Roman/Martin Could you provide some context/explanation to help me to understand the solution? ; my initial read from this is that we are creating a extension function to a property called “bd” that call a method toBigDecimal() which needs to be implemented. Is it correct? Thanks for the help!
m

Martin

10/13/2020, 8:14 AM
The Kotlin standard library already defines
toBigDecimal()
as an extension function on the
Int
type, so you don't need to implement that. @elizarov's solution is adding a
bd
property to the
Int
type, and the getter for that property delegates to
toBigDecimal()
. That way,
EmployeeRunData
only needs the primary constructor, which takes a
BigDecimal
, and you can call it like:
val constructWithBigDecimal = EmployeeRunData(<http://10.bd|10.bd>)
. Does that make more sense?
💯 1
👍 1
j

Juan B

10/13/2020, 3:51 PM
Thanks a lot @Martin . It makes sense!!
👍 1