## Operator overloading Kotlin

method overloading in kotlin

kotlin operator fun invoke

kotlin operator precedence

division operator overloading kotlin

kotlin operator overloading string division

kotlin operator overloading equals

kotlin overload assignment operator

I'm new to kotlin and I'm working on operators overloading for a custom class I defined. The class is called "Rational" and represents a rational number, like for example 117/1098. Class is defined as below and I have overloaded a bunch of operators, like plus, minus, times and so on. However I'm uncertain about what I have to do to overload "in" operator.

Here is my class:

data class Rational(val rational: String) { private val numerator: BigInteger private val denominator: BigInteger init { val splitted = rational.split("/") numerator = splitted[0].toBigInteger() denominator = when (splitted[1]) { "0" -> throw Exception("not allowed") else -> splitted[1].toBigInteger() } } operator fun plus(number: Rational): Rational { val gcm = denominator * number.denominator val numerator = (gcm / denominator) * numerator + (gcm / number.denominator) * number.numerator return Rational("$numerator/$gcm") } operator fun minus(number: Rational): Rational { val gcm = denominator * number.denominator val numerator = (gcm / denominator) * numerator - (gcm / number.denominator) * number.numerator return Rational("$numerator/$gcm") } operator fun times(number: Rational): Rational { val numerator = numerator * number.numerator val denominator = denominator * number.denominator return Rational("$numerator/$denominator") } operator fun div(number: Rational): Rational { val numerator = numerator * number.denominator val denominator = denominator * number.numerator return Rational("$numerator/$denominator") } operator fun compareTo(number: Rational): Int { val ratio = this.numerator.toFloat() / this.denominator.toFloat() val numberRatio = number.numerator.toFloat() / number.denominator.toFloat() if (ratio > numberRatio) { return 1 } else if (ratio == numberRatio) { return 0 } return -1 } operator fun unaryMinus(): Rational { val inverseNumerator = -numerator return Rational("$inverseNumerator/$denominator") } operator fun unaryPlus(): Rational { return Rational("$numerator/$denominator") } operator fun rangeTo(end: Rational): Any { var range: MutableList<Rational> = arrayListOf() val startNumerator = this.numerator.toInt() val endNumerator = end.numerator.toInt() var index = 0 if (this.denominator == end.denominator) { for (i in startNumerator..endNumerator) { range.add(index, Rational("$i/$denominator")) } } return range } operator fun contains(number: Rational): Boolean { if (this.denominator % number.denominator == 0.toBigInteger() && this.numerator <= number.numerator) { return true } return false } override fun toString(): String { val gcd = numerator.gcd(denominator) return if (gcd != null) { val newNumerator = numerator / gcd val newDenominator = denominator / gcd "$newNumerator/$newDenominator" } else { "$numerator/$denominator" } } }

infix fun Int.divBy(denominator: Int): Rational { if (denominator == 0) { throw Exception("denominator 0 not allowed") } return Rational("$this/$denominator") } infix fun Long.divBy(denominator: Long): Rational { if (denominator == 0L) { throw Exception("denominator 0 not allowed") } return Rational("$this/$denominator") } infix fun BigInteger.divBy(denominator: BigInteger): Rational { if (denominator == 0.toBigInteger()) { throw Exception("denominator 0 not allowed") } return Rational("$this/$denominator") } fun String.toRational(): Rational { return Rational(this) }

And here is my main body that obviously still doesn't compile:

fun main() { val half = 1 divBy 2 val third = 1 divBy 3 val twoThirds = 2 divBy 3 println(half in third..twoThirds) // this line does not compile beacause in operator is not defined for the class }

I guess I have to override "rangeTo" operator but I'm uncertain about the operator prototype. I there somebody that can please help me to get to the right track?

The way to make `in`

work is for the `third..twoThirds`

call to return *something* that has a `contains(Rational)`

method, which is what the `in`

call translates to.

One way to do this is to return a `ClosedRange<Rational>`

here, like so:

operator fun rangeTo(end: Rational): ClosedRange<Rational> { return object : ClosedRange<Rational> { override val endInclusive: Rational = end override val start: Rational = this@Rational } }

This puts a type constraint on `Rational`

, as a `ClosedRange`

needs a `Comparable`

implementation to be able to determine whether a value belongs in it. You can do this by implementing the `Comparable`

interface, and then adding `operator`

to your existing `compareTo`

operator (plus it's a good practice to rename the parameter to match the interface):

data class Rational(val rational: String) : Comparable<Rational> { ... override operator fun compareTo(other: Rational): Int { val ratio = this.numerator.toFloat() / this.denominator.toFloat() val numberRatio = other.numerator.toFloat() / other.denominator.toFloat() if (ratio > numberRatio) { return 1 } else if (ratio == numberRatio) { return 0 } return -1 } }

You could also avoid the conversion to floats entirely by using this implementation instead, as suggested in the comment below by @gidds:

override operator fun compareTo(other: Rational): Int { return (numerator * other.denominator - denominator * other.numerator).signum() }

Also, your current `contains`

implementation could *probably* be discarded, as you no longer need it, and it functions rather oddly.

To add something other than the direct answer here: as @Eugene Petrenko suggested in their answer, it would be practical to add a couple constructors other than the one that uses a `String`

, for example one that takes two `Int`

s, and one that takes two `BigIntegers`

s.

**Operator Overloading in Kotlin,** Overloaded operators are not always commutative. That is, we can't swap the operands and expect things to work as smooth as possible. Operator Overloading in Kotlin 1. Overview. In this tutorial, we're going to talk about the conventions that Kotlin provides to support operator 2. The operator Keyword. In Java, operators are tied to specific Java types. For example, String and numeric types in 3. Overloading for Unary

The `in`

operator is declared inverse. You need an extension function on the right side that takes the left side.

https://kotlinlang.org/docs/reference/operator-overloading.html#in

You miss an infix function `divBy`

to allow turing `Int`

into `Rational`

, e.g.

infix fun Int.divBy(i: Int) = Rational("$this/$i")

Not the code like `val half = 1 divBy 2`

will work. Theoretically, it may make sense to add a constructor for `Rational`

from `Int`

s to avoid parsing.

There is an incorrect return type in `rangeTo`

method in the `Rational`

class, it should not be `Any`

. It should be declared as

data class RationalRange(val left: Rational, val right: Rational) { operator fun contains(r: Rational) = left <= r && r <= right } operator fun rangeTo(end: Rational): RationalRange(this, end)

Now the example with `x in a..b`

should work.

UPD: added the RationalRange. I missed the point, sorry. You do not need `contains`

function implemented for the `Rational`

class at all.

The `compareTo`

function of `Rational`

is unlikely to use `.toFloat()`

instead, you may implement that directly with integer numbers

**Kotlin Operator Overloading (With Examples),** In this article, you will learn about operator overloading (define how operator works for user defined types like objects) with the help of examples. When you use� Operator overloading Kotlin allows us to overload some operators on any object we have created, or that we know of (through extensions). The concept of operator overloading provides a way to invoke functions to perform arithmetic operation, equality checks or comparison on whatever object we want, through symbols like +, -, /, *, %, <, >.

A straightforward solution is to implement the Comparable Interface in your class.

`data class Rational(val rational: String) : Comparable<Rational>`

Then implement the compareTo() function, with your comparison logic.

override fun compareTo(other: Rational): Int { //Normalize the numerators of each rational val thisNumerator = this.numerator * other.denominator val otherNumerator = other.numerator * this.denominator //Then compare them return when{ thisNumerator > otherNumerator -> 1 thisNumerator < otherNumerator -> -1 else -> 0 } }

This will resolve the compile error without you needing to override the rangeTo() function with custom logic.

**Kotlin Operator Overloading,** Kotlin Operator Overloading. Since Kotlin provides user-defined types, it also provides the additional functionality to overload the standard operators, so that� We looked at what operator overloading is and how to do it in Kotlin. We see that the operators serve as a shorthand for function calls, and consequently anything written with an operator can be written explicitly with the corresponding function.

**Operator overloading in Kotlin,** Kotlin has a fixed number or symbolic operators we can easily use on any class. The way is to create a function with a reserved name that will be mapped to the� Kotlin supports a technique called conventions, everyone should be familiar with. For example, if you define a special method plus in your class, you can use the + operator by convention: Kotlin Operator Overloading.

**[Kotlin] Operator overloading,** Operator overloading. Kotlin allows us to overload some operators on any object we have created, or that we know of (through extensions). The concept of� And because there is no way to define a class of a function type in kotlin then implement operator overloading as a member function of a function. – Sero Mar 31 '17 at 22:50 1 For functional types yes, but any class that has an open invoke function can be overridden.

**When exactly is the operator keyword required in Kotlin?,** The operator overloading docs linked to from the exercise explicitly says: Functions that overload operators need to be marked with the operator� operator marks a function as overloading an operator or implementing a convention out marks a type parameter as covariant override marks a member as an override of a superclass member private marks a declaration as visible in the current class or file

##### Comments

- As a matter of design, I'd suggest adding a constructor that takes a pair of
`BigInteger`

s. You can then do the GCD calculation there, instead of in`toString()`

. Avoiding all the conversion of`BigInteger`

s to`Strings`

s and back again should save memory and time, as well as simplifying the code a bit. You'll probably also want to override`equals()`

and`hashCode()`

, along with operators`inc()`

, and`dec()`

. If you override`toByte()`

&c, you can implement`Number`

too. And why define`compareTo()`

without implementing`Comparable`

? — Yes, I've implemented a`Rational`

class too :-) `compareTo()`

doesn't need to do any division or conversions at all: you could just do e.g.`(numerator * other.denominator - denominator * other.numerator).sign`

.- Oops, of course! I'll add this to the answer itself as well, thank you!
- Thanks for all your help :) everything works fine now!
`rangeTo`

should most definitely not return a`Rational`

, it makes no sense to then check if a`Rational`

contains another.- @Eugene, thanks a lot. Makes more sense know. I have indeed defined infix functions but I forgot to cut & paste them, going to update the question
- Thanks for all your help :) everything works fine now!