Lesson 42 – Overloading operators in Kotlin Programming Language

Lesson 42 – Overloading operators in Kotlin Programming Language

Hello viewer, You can now have our Tutorial Lessons in your android mobile device and read it offline.
Download kotlin Programming APP on PlayStore
Download Website SEO Lessons APP on PlayStore

The Kotlin language allows certain operators to be overloaded and to act in different ways according to the object that is applied.

Operator overloading should be used as long as it makes sense for the class being deployed. Mathematical concepts of vectors and matrices are cases where the overload of operators can make our code more readable and elegant.

To overload the +, -, * and / operators we must implement a series of special methods within the class:

Operation Name of the method to be defined
A + b plus
A - b minus
A * b times
A / b div
A% b rem
A..b rangeTo

Problem 1

Declare a class named Vector that manages an array of 5 integer elements and loads random values between 1 and 10. Overloading the +, -, * and / or operators
In the main define a series of objects of the Vector class and operate with them

Project162 

class Vector {
    val array = IntArray (5)

    fun load () {
        for (i in array.indices)
            array [i] = (Math.random () * 11 + 1) .toInt ()
    }
// www.coding180.com
    fun print () {
        for (element in array)
            print ("$element")
        println ()
    }
    operator fun plus (vector2: Vector): Vector {
        var sum = Vector ()
        for (i in array.indices)
            sum.array [i] = array [i] + vector2.array [i]
        return sum
    }

    operator fun minus (vector2: Vector): Vector {
        var subtract = Vector ()
        for (i in array.indices)
            subtract.array[i] = array [i] - vector2.array [i]
        return subtract
    }

    operator fun times (vector2: Vector): Vector {
        var product = Vector ()
        for (i in array.indices)
            product.array [i] = array [i] * vector2.array [i]
        return product
    }

    operator fun div (vector2: Vector): Vector {
        var division = Vector ()
        for (i in array.indices)
            division.array [i] = array [i] / vector2.array [i]
        return division
    }
}

fun main (args: Array <String>) {
    val vec1 = Vector ()
    vec1.load ()
    val vec2 = Vector ()
    vec2.load ()
    vec1.print ()
    vec2.print ()
    
    val vecSum = vec1 + vec2
    println ("Sum component to component of the two vectors")
    vecSum.print()
    
    val vecSub = vec1 - vec2
    println ("The component-to-component subtraction of the two vectors")
    vecSub.print ()
    
    val vecProduct = vec1 * vec2
    println ("The product component to component of the two vectors")
    vecProduct.print ()
    
    val vecDivision = vec1 / vec2
    println ("The component-to-component division of the two vectors")
    vecDivision.print ()
}

To overload the + operator we must implement the plus method that receives a single parameter, in this case of type Vector and returns another object of the Vector class.

We must precede the keyword fun with the keyword operator.
Within the method we create an object of class Vector and proceed to initialize its property array with the sum component to component of the two arrangements of each object:

    Operator fun plus (vector2: Vector): Vector {
        Var sum = Vector ()
        For (i in array.indices)
            Sum.array [i] = array [i] + vector2.array [i]
        Return sum
    }

To call this method in the main we use the + operator:

    Val vecSum = vec1 + vec2

The other syntax that we can use is the one already known to invoke the method:

    Val vecSum = vec1.plus (vec2)

With this, we can verify that the program is more readable using the + operator.

Let’s think that if we have to add 4 vectors the syntax would be:

    Val vecSum = vec1 + vec2 + vec3 + vec4

In complex algorithms, our code can greatly simplify the correct use of operator overload.

We can overload an operator with objects of different kinds.

Problem 2

Declare a class named Vector that manages an array of 5 integer elements and loads random values between 1 and 10. Overloading the * operator to multiply a Vector with an integer (multiply each component of the array by the integer)

Project163

class Vector {
    val array = IntArray (5)
// www.coding180.com
    fun load () {
        for (i in array.indices)
            array [i] = (Math.random () * 11 + 1) .toInt ()
    }

    fun print () {
        for (element in array)
            print ("$element")
        println ()
    }

    operator fun times (value: Int): Vector {
        var sum = Vector ()
        for (i in array.indices)
            sum.array [i] = array [i] * value
        return sum
    }
}

fun main (args: Array <String>) {
    val vec1 = Vector ()
    vec1.load ()
    vec1.print ()
    println ("The product of a vector with the number 10 is")
    val vecProductoEnt = vec1 * 10
    vecProductoEnt.print ()
}

In this problem to overload the * operator of a Vector by an integer type to the method must arrive an int data type:

    Operator fun times (value: Int): Vector {
        Var sum = Vector ()
        For (i in array.indices)
            Sum.array [i] = array [i] * value
        Return sum
    }

In the main function when we multiply an object of the class Vector by a data type Int we must do it in this order:

    Println ("The product of a vector with the number 10 is")
    Val vecProductoEnt = vec1 * 10
    VecProductEnt.print ()

If we inverse the product, i.e an Int by a Vector, we must define the times method in the Int class. The complete program would then be:

class Vector {
    val array = IntArray (5)

    fun load () {
        for (i in array.indices)
            array [i] = (Math.random () * 11 + 1) .toInt ()
    }

    fun print () {
        for (element in array)
            print ("$element")
        println ()
    }

    operator fun times (value: Int): Vector {
        var sum = Vector ()
        for (i in array.indices)
            sum.array [i] = array [i] * value
        return sum
    }
}

operator fun Int.times (vec: Vector): Vector {
    var sum = Vector ()
    for (i in vec.array.indices)
        sum.array [i] = vec.array [i] * this
    return sum
}

fun main (args: Array <String>) {
    val vec1 = Vector ()
    vec1.load ()
    vec1.print ()
    // www.coding180.com
    println ("The product of a vector with the number 10 is")
    val vecProductoEnt = 10 * vec1
    vecProductoEnt.print ()
    println ("The product of an integer 5 by a vector is")
    val vecProductoEnt2 = vec1 * 5
    vecProductoEnt2.print ()

}

We use the concept of extension functions that we saw earlier:

Operator fun Int.times (vec: Vector): Vector {
    Var sum = Vector ()
    For (i in vec.array.indices)
        Sum.array [i] = vec.array [i] * this
    Return sum
}

Problem 3

Declare a class named Vector that manages an array of 5 integer elements and loads random values between 1 and 10. Overloading the ++ and – operators (you must increase or decrease each element of the array by one)

Project 164

class Vector {
    val array = IntArray (5)
// www.coding180.com
    fun load () {
        for (i in array.indices)
            array [i] = (Math.random () * 11 + 1) .toInt ()
    }

    fun print () {
        for (element in array)
            print ("$element")
        println()
    }

    operator fun inc (): Vector {
        var sum1 = Vector ()
        for (i in array.indices)
            sum1.array [i] = array [i] + 1
        return sum1
    }

    operator fun dec (): Vector {
        var remains1 = Vector ()
        for (i in array.indices)
            remains1.array [i] = array [i] - 1
        return remains1
    }
}


fun main (args: Array <String>) {
    var vec1 = Vector ()
    vec1.load ()
    println ("Original Vector")
    vec1.print ()
    vec1 ++
    println ("After calling operator ++")
    vec1.print ()
    vec1--
    println ("After calling the operator -")
    vec1.print ()
}

When we want to overload the operators ++ and – we must implement the methods inc and dec. These methods do not receive any parameters and return objects of the Vector class by increasing by one or decreasing by one each component of the array:

    Operator fun inc (): Vector {
        Var sum1 = Vector ()
        For (i in array.indices)
            Sum1.array [i] = array [i] + 1
        Return sum1
    }

    Operator fun dec (): Vector {
        Var remains1 = Vector ()
        For (i in array.indices)
            remains1.array [i] = array [i] - 1
        Return remains1
    }

When we call the operators ++ and – the object that returns is assigned to the variable by which we call, this makes it necessary to define the object of the class Vector with the keyword var:

    Var vec1 = Vector ()
    Vec1.load ()
    Println ("Original Vector")
    Vec1.print ()

Once the operator ++ is called:

    Vec1 ++

Now vec1 has the reference to the object that was created in the method inc:

    Println ("After calling operator ++")
    Vec1.print ()

No changes need to be made if we need to use prefix notation with ++ and – operators:

    ++ vec1
    --vec1

Overloading operators>> = y <<=

To overload these operators we must implement the compareTo method.

Problem 4

Implement a class called Person that will have properties like their name and age. Overload the operators >> = and <<=.

Project165

class Person (val name: String, val age: Int) {

    fun print () {
        println ("Name: $name and has an age of $age")
    }
// www.coding180.com
    operator fun compareTo (per2: Person): Int {
        return when {
            age < per2.age -> -1
            age > per2.age -> 1
                    else -> 0
        }
    }
}

fun main (parameter: Array <String>) {
    val person1 = Person ("Juan", 30)
    person1.print()
    
    val person2 = Person ("Ana", 30)
    person2.print ()
    println ("Elderly person")
    when {
        person1> person2 -> person1.print ()
        person1 <person2 -> person2.print ()
        else -> println ("They are the same age")
    }
}

The compareTo method must return an Int, indicating that if it returns a 0 the two people are the same age. If you return 1, the person to the left of the operator is of legal age and vice versa:

    Operator fun compareTo (per2: Person): Int {
        Return when {
            Age <per2.age-> -1
            Age> per2.age -> 1
            Else -> 0
        }
    }

Then we can ask with these operators for objects of the class Person which has a greater age:

    When {
        Person1 > person2 -> person1.print ()
        Person1 < person2 -> person2.print ()
        Else -> println ("They are the same age")
    }

Overload of subscripts operators

In Kotlin we can overload the handling of subscripts by implementing the get and set methods.

The expression translates
A [i] = b a.set (i, b)
A [i, j] = b a.set (i, j, b)
A [i_1, ..., i_n] = b a.set (i_1, ..., i_n, b)

To [i] a.get (i)
A [i, j] a.get (i, j)
To [i_1, ..., i_n] a.get (i_1, ..., i_n)

Problem 5

Implement a TaTeTi class that defines a property for the board that is an IntArray of 9 elements with a zero value.
There are two players who have chips, the first player loads the 1 and the second one loads a 2.
By means of subscripting operators, overload allow assigning the chips to each position of the board by means of two subscripts that indicate the row and column of the board.

Project166

class TaTeTi {
    val table = IntArray (9)
// www.coding180.com
    fun print () {
        for (row in 0..2) {
            for (column in 0..2)
                print ("${this 
}") println () } println () } operator fun set (row: Int, column: Int, value: Int) { table
= value print() } operator fun get (row: Int, column: Int): Int { return table
} } fun main (args: Array <String>) { val game = TaTeTi () game [0, 0] = 1 game [0, 2] = 2 game [2, 0] = 1 game [1, 2] = 2 game [1, 0] = 1 }

The Table property stores the nine boxes of the game in an array. In order to be more intuitive the loading of chips in the game of tateti, we proceed to overload the operator of subscripts with row and column.

The idea is that we can indicate a row, column and the tab that is loaded with the syntax:

    Game [0, 0] = 1
    Game [0, 2] = 2
    Game [2, 0] = 1
    Game [1, 2] = 2
    Game [1, 0] = 1

Each assignment actually calls the set method, which in addition to loading the tab goes to print the board:

    Operator fun set (row: Int, column: Int, value: Int) {
        table
= value to print() }

The board impression proceeds to access the overload of the subscript operator by accessing the get method:

    Fun print () {
        For (row in 0..2) {
            For (column in 0..2)
                Print ("$ {this 
}") Println () } Println () }

The overload to retrieve the stored value is done by implementing the get method:

    Operator fun get (row: Int, column: Int): Int {
        Return table
}

Remember that the overload of operators aims to make our program more readable, here we succeed because it is very easy to understand how we load the chips on the board with the assignment:

    Val game = TaTeTi ()
    Game [0, 0] = 1

Let’s always keep in mind that when an operator is overloaded it is actually calling a class method.

The execution of this program shows us on the screen the successive states of the Tateti table as we assign pieces to it:

Lesson 42 - Overloading operators in Kotlin Programming Language - Lesson 42 - Overloading operators in Kotlin Programming Language - Lesson 42 - Overloading operators in Kotlin Programming Language - Overloading operators in Kotlin Programming Language
Overloading operators in Kotlin Programming Language

Parenthesis Overload

In Kotlin we can also overload the parentheses by implementing the invoke method.

The expression translates
To () a.invoke ()
To (i) a.invoke (i)
To (i, j) a.invoke (i, j)
To (i_1, ..., i_n) a.invoke (i_1, ..., i_n)

Problem 6

Raise a class Data that manages 10 data values in an array of type IntArray.
Overload the parentheses operator for the class and access by a position the value of a specific data.

Project167 

class Data  {

    val array = IntArray (10)

    fun withdraw () {
        for (i in array.indices)
            array [i] = ((Math.random () * 6) + 1) .toInt ()
    }

    operator fun invoke (nro: Int) = array [nro]
}

fun main (args: Array <String>) {
    var data = Data ()
    data.withdraw ()
    println (data (0))
    println (data (1))
    for (i in 2..9)
        println (data (i))
}

 

We declare an array of 10 integers and store random values between 1 and 6:

Class Data () {

    Val array = IntArray (10)

    Fun withdraw () {
        For (i in array.indices)
            Array [i] = ((Math.random () * 6) + 1) .toInt ()
    }

In the main function we create the object of the Data class and call the withdraw method:

    Var data = Data ()
    Data.withdraw()

Then if we have the name of the object and in parentheses, we pass an integer will call the method invoke and will return in this case an integer that represents the value of the die for that position:

    Println (data (0))
    Println (data (1))
    For (i in 2..9)
        Println (data (i))

In the Data class we specify the overhead of the parentheses operator with the implementation of the invoke method:

    Operator fun invoke (nro: Int) = array [nro]

For this problem, we could also have overloaded the bracket operator as we saw earlier.

The choice of which operator to overload depends on the problem to be developed and to see which is clearer its use.

Overload of operators + = – = * = / =% =

The methods invoked for these operators are:

The expression translates
A + = b a.plusAssign (b)
A - = b a.minusAssign (b)
A * = b a.timesAssign (b)
A / = b a.divAssign (b)
A% = b a.modAssign (b)

Problem 7

Declare a class called Vector that manages an array of 5 integer elements.
Overload the operator + =
In the main define a series of objects of the class and use the operator + =

Project168

class Vector {
    val array = IntArray (5, {it})

    fun print () {
        for (element in array)
            print ("$element")
        println ()
    }

    operator fun plusAssign (vec2: Vector) {

        for (i in array.indices)
            array[i] += vec2.array [i]
    }
}

fun main (args: Array <String>) {
    val vec1 = Vector ()
    vec1.print ()
    val vec2 = Vector ()
    vec2.print ()
    vec1 += vec2
            vec1.print ()
}

To overload the + = operator in the Vector class we define the plusAssign method:

    Operator fun plusAssign (vec2: Vector) {

        For (i in array.indices)
            Array[i] + = vec2.array [i]
    }

The method reaches an object of the class Vector that serves to access the array contained in it.

In the main function we define two objects of class Vector and proceed to accumulate in vec1 the contents of vec2 by the + = operator:

Fun main (args: Array <String>) {
    Val vec1 = Vector ()
    Vec1.print ()
    Val vec2 = Vector ()
    Vec2.print ()
    Vec1 + = vec2
    Vec1.print ()
}

Overload of operators in y! In

The methods invoked for these operators are:

The expression translates
A in b b.contains (a)
A! In b! B.contains (a)

Problem 8

Raise a data class Student to store their document number and name.
Then in a Course class define an Array with 3 objects of the Student class. Overload the in operator to verify if a document number is enrolled in the course.

Project169

data class Student (val document: Int, val name: String)
// www.coding180.com
class Course {
    val students = arrayOf (Student (123456, "Mark"),
            Student (666666, "Ana"),
            Student (777777, "Luis"))

    operator fun contains (document: Int): Boolean {
        return students.any {document == it.document}
    }
}

fun main (args: Array <String>) {
    val course1 = Course ()
    if (123456 in course1)
        println ("Student Marcos is enrolled in the contract")
    else
        println ("Marcos student is not enrolled in the contract")
}

We declare a data class that represents a Student:

Data class Student (val document: Int, val name: String)

We declare the class Courses defining an Array with four students:

Class Course {
    Val students = arrayOf (Student (123456, "Marcos"), Student (666666, "Ana"), Student (777777, "Luis"))

We overloaded the operator in:

    Operator fun contains (document: Int): Boolean {
        Return students.any {document == it.documento}
    }

The method returns an integer representing the document number to be searched within the student array. In the case that we find a true return, in the negative case, we return a false.

We can write more concisely the contains method:

    Operator fun contains (document: Int) = students.any {document == it.document}

In the main, we create an object of the class course and then through the operator in we can verify if a certain number of document is registered in the course of students:

Fun main (args: Array <String>) {
    Val course1 = Course ()
    If (123456 in course1)
        Println ("Student Marcos is enrolled in the contract")
    Else
        Println ("Marcos student is not enrolled in the contract")
}

About The Author

Related posts

Leave a Reply