Maintaining an up to date currency list is, quite frankly, hell. Your code will always, always be more up to date than said list.
private data class Money<T>(val name: String, val amount: Int) {
operator fun <U : T> plus(other: Money<U>): Money<T> {
return Money(name, amount + other.amount)
}
fun <U> plus(other: Money<U>, converter: (Money<U>) -> Money<T>): Money<T> {
return converter(other) + this
}
}
private object EUR
private object USD
val eur = Money<EUR>("EUR", 10)
val usd = Money<USD>("USD", 20)
usd + eur // error
This gives you entirely user defined currencies, does not pollute the global scope with unneeded currencies, allows you to plug in any conversion technique (pop off, make a network call), and fails if you try to add USD and EUR without converting one into the other.Currencies should always be the user's responsibility to provide.
I feel like you're jumping to wild conclusions. All I'm suggesting is to change your code to
private object EUR : Currency
private object USD : Currency
data class Money<C : Currency>(...) { ... }
That's just an empty tag interface and that's not particularly hardcore OOP, you can do the same thing with Haskell typeclasses.