I would like to achieve something where I could call a data class with either an Int
or BigDecimal
type. So for example:
data class Money(val amount: Int, val currencyCode: CurrencyCode) {
fun toSmallestUnit(): Int = when (this.currencyCode) {
CurrencyCode.USD -> this.amount * 100
CurrencyCode.EUR -> this.amount * 100
}
}
Here I would like to be able to send both Int
and BigDecimal
as an amount to data class Money
, and then have different toSmallestUnit
function for each type. How can I achieve this in Kotlin?
CodePudding user response:
One way to do it is like this
data class Money<T>(val amount: T, val currencyCode: CurrencyCode) {
fun toSmallestUnit(): T = when(amount) {
is Int -> {
when (this.currencyCode) {
CurrencyCode.USD -> (this.amount * 100) as T
CurrencyCode.EUR -> (this.amount * 100) as T
}
}
is BigInteger -> {
when (this.currencyCode) {
CurrencyCode.USD -> this.amount.multiply(BigInteger("100")) as T
CurrencyCode.EUR -> this.amount.multiply(BigInteger("100")) as T
}
}
else -> {
amount
}
}
}
toSmallestUnit
will return the right result type depending on the type. But as you can see it then does allow to create Money
of any type
CodePudding user response:
Every time you use this class in code, the compiler has to know which type amount
is for you to be able to do anything with it. If we were working with your own classes, you could define an interface that they both implement, but this is not possible with Int/BigDecimal.
So, I propose you design your class to simply use BigDecimal as the type of amount
, and provide constructors and properties to allow it to convert from Int.
This is just an example. I'm not sure how it makes sense to convert a currency in BigDecimal to an integer.
data class Money(val amount: BigDecimal, val currencyCode: CurrencyCode) {
constructor(amount: Int, currencyCode: CurrencyCode): this(amount.toBigDecimal(), currencyCode)
val intAmount: Int get() = amount.toInt()
fun toSmallestUnit(): Int = when (this.currencyCode) {
CurrencyCode.USD -> intAmount * 100
CurrencyCode.EUR -> intAmount * 100
}
}