I am trying to do this
infix fun Int.divBy (_denom: Int): Rational {
var num = this.toBigInteger()
var denom = _denom.toBigInteger()
// reduce result
val result = Rational(num, denom)
result.reduce()
// return
println("Returning: Rational $result")
return result
}
but for Long, Int and BigInteger, and without having to rewrite the same for all of them. I tried this, but I get an error:
infix fun <T> T.divBy (_denom: T): Rational where
T: Int, T:BigInteger, T: Long
{
....
}
So that things like val third = 1 divBy 3
can be done.
CodePudding user response:
I believe this is not possible, because there is no interface for "something convertable to BigInteger". Still, you can keep most of your code in a single function receiving BigInteger
objects and provide multiple functions for just converting to BigInteger
:
infix fun Int.divBy(denom: Int): Rational = toBigInteger() divBy denom.toBigInteger()
infix fun Long.divBy(denom: Long): Rational = toBigInteger() divBy denom.toBigInteger()
inline infix fun BigInteger.divBy (denom: BigInteger): Rational {
// reduce result
val result = Rational(this, denom)
result.reduce()
// return
println("Returning: Rational $result")
return result
}
Edit (@ademord): the final solution looks like this, after cleaning it up:
infix fun Int.divBy(denom: Int): Rational = toBigInteger() divBy denom.toBigInteger()
infix fun Long.divBy(denom: Long): Rational = toBigInteger() divBy denom.toBigInteger()
infix fun BigInteger.divBy (denom: BigInteger): Rational = Rational(this, denom).reduce()
As a side note, it can't be done with generics and upper bounds, because their main purpose is that the code inside the function knows what is the type of T
. where
clause is used to specify multiple requirements that T
needs to satisfy altogether. Upper bounds are ANDed, not ORed. Note that if they would be ORed then we would still have to add runtime type checks and casts, which is exactly what we try to avoid providing upper bounds (thanks @Tenfour04 for pointing this out).