Skip to content

MADS 4013 Introduction to Kotlin

image.png
image.png
Lecture Summary
Session 01: Tuesday Feb 21
Click here. jump to the content:
Topics covered:
Familiarizing yourself with Intellij IDEA
Kotlin Syntax
The main() function (Activity #A)
Creating variables with val and var
Output to console with println and $ symbol
Conditionals
For loop, while loop
Declaring and using a function with and without parameters
Fixed size arrays (arrayOf), dynamically sized arrays (listOf)
Looping through an array (Activity #D)
How to generate random numbers
Session 02: Wed Feb 22:
Click here to jump to the content:
Topics Discussed:
Declaring a class and its constructor
What is. constructor, how is it used
What are class properties and how are they used
Providing a default value to a class property
Developing class-oriented programs (Example: )
Session 01 - Tuesday Feb 21
Installing IntelliJ
Kotlin is a popular programming language that supports various programming paradigms, including object-oriented and functional programming.

Looping enables developers to iterate over a set of values or execute a block of code repeatedly. Here are the types of loops available in Kotlin:
For loop: A for loop in Kotlin is used to iterate over a range, an array, a collection, or any object that provides an iterator. The syntax of the for loop is similar to that of Java and other programming languages. You can also use a for loop to iterate over a string using the indices property.
While loop: A while loop in Kotlin is used to execute a block of code repeatedly while a specified condition is true. The while loop evaluates the condition before each iteration and stops when the condition becomes false.
Do-While loop: The do-while loop in Kotlin is similar to the while loop, except that it executes the block of code at least once, even if the condition is false. The condition is evaluated after each iteration, and the loop stops when the condition becomes false.

Activity A
Here's a Kotlin code example that adds two numbers together and prints the result to the console:
fun main() { val num1 = 5 val num2 = 7 val sum = num1 + num2 println("The sum of $num1 and $num2 is $sum") }

This program declares two variables num1 and num2, each containing an integer value. It then declares a third variable sum that is the result of adding num1 and num2. Finally, it prints a message to the console using string interpolation to display the values of num1, num2, and sum.
Activity B: Game Scenario: Guess the Number
In this game, the program chooses a random number between 1 and 10, and the player has to guess the number. If the player's guess is correct, they win the game. If their guess is incorrect, the program tells them whether the actual number is higher or lower than their guess, and they get to guess again. The game ends after the player correctly guesses the number or after they have made 3 incorrect guesses.
This game scenario is simple enough to be implemented using basic Kotlin programming concepts like random number generation, user input, conditional statements, and loops. It can be a good introduction to the language for beginners who are just starting out.

import kotlin.random.Random
fun main() { val secretNumber = Random.nextInt(1, 11) var numGuesses = 0 var guessedCorrectly = false println("Welcome to Guess the Number! You have 3 attempts to guess the number between 1 and 10.") while (numGuesses < 3 && !guessedCorrectly) { print("Guess #$numGuesses: ") val guess = readLine()?.toIntOrNull() if (guess == null) { println("Invalid input. Please enter a number between 1 and 10.") } else if (guess == secretNumber) { guessedCorrectly = true println("Congratulations, you guessed the number!") } else if (guess < secretNumber) { println("Your guess is too low. Try again.") } else { println("Your guess is too high. Try again.") } numGuesses++ } if (!guessedCorrectly) { println("Sorry, you did not guess the number. The secret number was $secretNumber.") } }

The program starts by generating a random number between 1 and 10 using the Random.nextInt() function from the Kotlin standard library. It then initializes two variables: numGuesses to keep track of the number of guesses the player has made, and guessedCorrectly to indicate whether the player has guessed the correct number.
The program then prints a welcome message and enters a while loop that executes as long as the player has made less than 3 incorrect guesses and has not guessed the correct number. Within the loop, the program prompts the player to make a guess and reads the player's input using the readLine() function. It then checks whether the input is a valid integer between 1 and 10 using the toIntOrNull() function. If the input is invalid, the program prints an error message. Otherwise, it checks whether the guess is correct, too low, or too high, and provides feedback to the player accordingly. It also increments the numGuesses counter.
After the loop has ended, the program checks whether the player has guessed the correct number. If they have, it prints a congratulatory message. If they have not, it prints a message indicating that the game is over and reveals the secret number to the player.
This program is relatively simple and uses basic Kotlin programming concepts like while loops, conditional statements (if-else), string interpolation, and the readLine() and toIntOrNull() functions to handle user input.


Activity C: ROCKS PAPER SCISSORS
The program starts by defining an array of the three possible choices. It then prompts the player to enter their name using the getPlayerName() function, and initializes the scores for both the player and the computer
import kotlin.random.Random
fun main() { val choices = arrayOf("Rock", "Paper", "Scissors") val playerName = getPlayerName() var playerScore = 0 var computerScore = 0 println("Hello $playerName, let's play Rock-Paper-Scissors!") while (playerScore < 3 && computerScore < 3) { val playerChoice = getPlayerChoice() val computerChoice = choices.random() println("$playerName chose $playerChoice") println("Computer chose $computerChoice") val roundWinner = determineRoundWinner(playerChoice, computerChoice) if (roundWinner == playerName) { playerScore++ println("$playerName wins the round!") } else if (roundWinner == "Computer") { computerScore++ println("Computer wins the round!") } else { println("It's a tie!") } println("Score: $playerName: $playerScore, Computer: $computerScore") } if (playerScore > computerScore) { println("$playerName wins the game!") } else { println("Computer wins the game!") } }
fun getPlayerName(): String { print("Please enter your name: ") return readLine() ?: "Player" }
fun getPlayerChoice(): String { print("Rock, Paper, or Scissors? ") var playerChoice = readLine() while (playerChoice !in arrayOf("Rock", "Paper", "Scissors")) { println("Invalid choice. Please choose Rock, Paper, or Scissors.") print("Rock, Paper, or Scissors? ") playerChoice = readLine() } return playerChoice }
fun determineRoundWinner(playerChoice: String, computerChoice: String): String { if (playerChoice == "Rock" && computerChoice == "Scissors" || playerChoice == "Scissors" && computerChoice == "Paper" || playerChoice == "Paper" && computerChoice == "Rock") { return "Player" } else if (playerChoice == "Rock" && computerChoice == "Paper" || playerChoice == "Scissors" && computerChoice == "Rock" || playerChoice == "Paper" && computerChoice == "Scissors") { return "Computer" } else { return "Tie" } }

Activity D: Here's an example Kotlin program that showcases loops, if statements, function calls, arrays, and lists:
fun main() {
val myArray = arrayOf(1, 2, 3, 4, 5)
val myList = listOf("apple", "banana", "cherry")

// Loop through an array and print each element
for (element in myArray) {
println("Array element: $element")
}

// Loop through a list and print each element
for (element in myList) {
println("List element: $element")
}

// Use an if statement to check if an array element is even
for (element in myArray) {
if (element % 2 == 0) {
println("$element is even")
}
}

// Call a function to print the sum of an array
val sum = getArraySum(myArray)
println("Sum of the array: $sum")
}

// Define a function to calculate the sum of an array
fun getArraySum(arr: Array<Int>): Int {
var sum = 0
for (element in arr) {
sum += element
}
return sum
}

In this program, we define an array myArray and a list myList, and then use loops to iterate through each of them and print their elements. We also use an if statement to check if each element of myArray is even. Finally, we call a function getArraySum to calculate the sum of myArray, and print the result.


More examples of Kotlin functions:
Here are additional code examples of functions can be used
Activity E: A simple function that takes in two integer parameters and returns their sum:

fun sum(a: Int, b: Int): Int {
return a + b
}

// Calling the function
val result = sum(2, 3)
println("The result is $result")

Output:

The result is 5



Activity F: A function that takes in a string and a default value as parameters, and returns the string if it is not null or empty, otherwise returns the default value:

fun getStringOrDefault(x: String?, y: String): String {
// if x == null, then "return y"
// if x != null, then "return x"
return x ?: y
}

// Calling the function
val str1 = getStringOrDefault("Hello", "ABC")
val str2 = getStringOrDefault(null, "ABC")
val str3 = getStringOrDefault("", "Default")

println(str1) // Output: Hello
println(str2) // Output: ABC
println(str3) // Output: Default

Activity G: A function that calculates the factorial of a given number using recursion:

fun factorial(n: Int): Int {
if (n == 0 || n == 1) {
return 1
}
return n * factorial(n - 1)
}

// Calling the function
val result = factorial(5)
println("The factorial of 5 is $result")

Output:

The factorial of 5 is 120

In each example, we declare the function using the fun keyword followed by the function name and the function's parameters in parentheses. The function's return type is specified after the parameter list with a colon followed by the type. The function body is enclosed in curly braces. To call the function, we simply use the function name followed by the arguments in parentheses.


5 examples of random number generation in Kotlin:
Generate a random integer between 1 and 100:

fun main() { ​for ( i in (1 .. 100)) { val randomINT = (1..100).random() println(randomINT); } }

Generate a random double between 0 and 1:

val randomDouble = Math.random()

Generate a random integer within a specific range:

val range = 10..20
val randomIntInRange = range.random()

fun main() { for ( i in (1 .. 100)) { val range = 10..20 val randomIntInRange = range.random() println(randomIntInRange) } }

fun main() { for ( i in (1 .. 100)) { val range = 10..20 val randomIntInRange = range.random() * 5 println(randomIntInRange) } }

fun main() { fun printRandomIntegersInStepsOfFive() { for (i in 1..100) { val range = 10..20 val randomIntInRange = range.random() * 5 println(randomIntInRange) } } printRandomIntegersInStepsOfFive() }
Generate a random boolean:

val randomBoolean = listOf(true, false).random()

Generate a random element from an array:

val items = arrayOf("apple", "banana", "orange")
val randomItem = items.random()

Note: To generate a random number, you can use the random() function available on different types, like IntRange, Double, List, or Array

Practice lab Test Question:
Solve the following requirement in KOTLIN:
Imagine Joe - invites you to a little gambling game.
One side of coin : number 5
Other side : number 10
Joe flips : wins double the number showing
You flip: wins double the number showing
game proceeds (3..10) times
keep track of who owns how much to who
printout number net amount owning

Wrap up all your logic in Functions


Session 02: 2023 February 22 Class
Example Kotlin program that uses classes:

class Person(var name: String, var age: Int) {
fun speak() {
println("Hello, my name is $name and I am $age years old.")
}
}

fun main() {
val person1 = Person("Alice", 25)
person1.speak()
val person2 = Person("Bob", 30)
person2.speak()
}

This program defines a Person class with two properties: name and age. The var keyword before the properties indicates that they are mutable and can be changed later on. The class keyword is used to define a new class.
Inside the Person class, there is a function called speak(). This function simply prints out a message that includes the name and age properties of the Person object.
In the main() function, we create two Person objects: person1 and person2. We pass in the name and age values as arguments to the constructor when we create each object.
Then, we call the speak() function on each Person object. This causes the Hello, my name is... message to be printed out, with the appropriate name and age values for each object.
When the program is run, the output should be:
pythonCopy code
Hello, my name is Alice and I am 25 years old.
Hello, my name is Bob and I am 30 years old.

Overall, this program demonstrates how to define a class in Kotlin, how to create objects of that class, and how to access the properties and methods of those objects.


Class oriented program to simulate a Library:
This program models a library system with two classes: Book and Library.
The Book class has three properties: title, author, and checkedOut. The checkedOut property is optional and defaults to false. The Book class also has two methods: checkOut() and checkIn(), which allow a book to be checked out or checked back in, respectively.
image.png
image.png
image.png
Explain the data structure in use here val books = mutableListOf<Book>()
In the example I provided, the Library class has a property called books, which is initialized as an empty mutable list of Book objects. This is achieved with the following code:

val books = mutableListOf<Book>()

The mutableListOf function is a Kotlin standard library function that creates a new mutable list, which can be modified by adding or removing elements. In this case, we want to create a list of Book objects, so we specify the type parameter as Book.
The books property is declared using the val keyword, which means it is a read-only property. However, since it is a mutable list, we can still modify its contents by adding or removing books.
The mutableListOf function returns a new MutableList object, which provides various methods for adding or removing elements, accessing elements by index, and so on. For example, to add a new Book object to the books list, we can use the add method, like this:
books.add(book)

This will append the book object to the end of the books list.
Overall, the mutableListOf function and the MutableList class provide a convenient way to create and manipulate lists of objects in Kotlin. They are often used in situations where we need to store a collection of objects that can be modified dynamically at runtime.

Explain the applicability of MutableList object to Android development
The M object is a very useful data structure in Android development. It is often used to represent collections of data that can be modified at runtime, such as lists of items in a RecyclerView, or lists of options in a Spinner or ListView.
Here are some specific examples of how MutableList can be used in Android development:
RecyclerView: A RecyclerView is a commonly used UI component that displays a list of items, such as images or text. The items are typically stored in a MutableList, which can be updated dynamically as new items are added or removed. The RecyclerView.Adapter class provides methods for interacting with the MutableList object, such as notifyDataSetChanged() to update the list when it changes.
Spinner: A Spinner is a UI component that displays a drop-down list of options, from which the user can select one. The options are typically stored in a MutableList, which can be modified dynamically to add or remove options. The ArrayAdapter class provides methods for interacting with the MutableList object, such as add() and remove() to modify the list of options.
ListView: A ListView is another UI component that displays a list of items, similar to a RecyclerView. The items are typically stored in a MutableList, which can be updated dynamically as new items are added or removed. The ArrayAdapter class provides methods for interacting with the MutableList object, such as add() and remove() to modify the list of items.
Overall, MutableList is a very versatile data structure that can be used in many different contexts in Android development. It provides a convenient way to store and modify collections of data, and it is ake each line of data (each record) into an AN OBJECT: these objects can be Anonymous (you don’t give them an object refsupported by many of the standard Android UI components and adapter classes.

More Objects: The Factory method:
Scenario: read in a CSV text file : each line of that text file is one record of data:
you can to merence name like book1). Ultimately, an object is a location in memory.
You don’t need to give your Object References NAMES: you can just work directly with the MEMORY LOCATION

An example Kotlin code that uses a Factory method to create objects and store them in an array:

If you apply an Interface to an OBJECT: Then you are saying:
The object to which the Interface is being applied MUST implement the stated Function (but HOW it does that is up to the object): The purpose of interfaces is to enable us to build component architectures in which all the Classes will work with each other in the prescribed way: Why? Because the INTERFACE conformity assures us that the data geometry of those classes will align to allow connection.
interface Shape {
fun draw()
}

class Circle : Shape {
override fun draw() {
println("Drawing a Circle")
}
}

class Square : Shape {
override fun draw() {
println("Drawing a Square")
}
}

class ShapeFactory {
companion object {
fun createShape(type: String): Shape? {
return when (type) {
"circle" -> Circle()
"square" -> Square()
else -> null
}
}
}
}

fun main() {
val shapes = arrayOfNulls<Shape>(3)

shapes[0] = ShapeFactory.createShape("circle")
shapes[1] = ShapeFactory.createShape("square")
shapes[2] = ShapeFactory.createShape("circle")

for (shape in shapes) {
shape?.draw()
}
}

This program defines an interface Shape with a single method draw(). The Circle and Square classes both implement the Shape interface and provide their own implementations of the draw() method.
The ShapeFactory class provides a createShape() method that takes a type argument and returns a new Shape object based on the value of the type argument. In this case, the createShape() method returns a Circle object if the type argument is "circle", a Square object if the type argument is "square", or null if the type argument is not recognized.
In the main() function, we create an array of Shape objects with a length of 3. We then use the ShapeFactory to create three Shape objects: a Circle, a Square, and another Circle. We store these objects in the shapes array.
Finally, we loop through the shapes array and call the draw() method on each Shape object, using the safe call operator (?.) to handle the case where the Shape object is null.
When the program is run, the output should be:
Drawing a Circle
Drawing a Square
Drawing a Circle

Overall, this program demonstrates how to use a Factory method to create objects of different types based on a single input value, and how to store these objects in an array for later use.

Explain the operator in use here "circle" -> Circle()

In the example I provided, the ShapeFactory class has a createShape() method that takes a type argument and returns a new Shape object based on the value of the type argument. This is achieved with the following code:
fun createShape(type: String): Shape? {
return when (type) {
"circle" -> Circle()
"square" -> Square()
else -> null
}
}

The when expression is a control structure in Kotlin that is similar to a switch statement in other languages. It allows you to compare a value against multiple cases and execute different code blocks depending on the matching case. In this case, we're using the when expression to create new Shape objects based on the value of the type argument.
The syntax case -> value is used to match a case and return a value. In this case, when the type argument is "circle", the -> operator is used to return a new Circle object, which is then assigned to the Shape variable. The Square class is similarly created when the type argument is "square". If the type argument is not recognized, we return null.
Overall, the -> operator is used in this context to match a case and return a value based on that case. It is a shorthand way of writing a conditional expression, and is often used in combination with the when expression in Kotlin.

Interacting with the User through the Command Line:
Kotlin code that handles input and output using appropriate user prompts and console output:
import java.util.Scanner ​import java.util.Random ​fun main() { val scanner = Scanner(System.`in`) println("Welcome to the coin flipping game!") println("Enter your name:") val name = scanner.nextLine() println("How many rounds do you want to play (between 3 and 10)?") var rounds = scanner.nextInt() while (rounds < 3 || rounds > 10) { println("Invalid input. Please enter a number between 3 and 10.") rounds = scanner.nextInt() } val joe = Player("Joe") val user = Player(name) val game = CoinFlippingGame(joe, user, rounds) game.play() println("Thanks for playing!") } ​class CoinFlippingGame(private val joe: Player, private val user: Player, private val rounds: Int) { private val coin = Coin(5, 10) private var round = 0 fun play() { while (round < rounds) { round++ println("Round $round") val joeFlip = coin.flip() val userFlip = coin.flip() joe.money -= joeFlip user.money += joeFlip user.money -= userFlip joe.money += userFlip println("Joe flipped $joeFlip, ${joe.name} now has ${joe.money}") println("${user.name} flipped $userFlip, ${user.name} now has ${user.money}") } if (joe.money > user.money) { println("${joe.name} wins!") } else if (user.money > joe.money) { println("${user.name} wins!") } else { println("It's a tie!") } println("${joe.name} owes ${user.name} ${joe.money - user.money}") println("${user.name} owes ${joe.name} ${user.money - joe.money}") } } ​class Player(val name: String) { var money = 0 ​} ​class Coin(private val side1: Int, private val side2: Int) { private val random = Random() fun flip(): Int { return if (random.nextBoolean()) side1 else side2 } }
In this example code, we use the Scanner class to handle user input. We prompt the user to enter their name and the number of rounds they want to play, and validate the input using a while loop to ensure that the number of rounds is between 3 and 10.
We then create a CoinFlippingGame object and call its play() method. The play() method uses console output to prompt the user for their moves, update the player objects, and print the current state of the game.
Finally, when the game is over, we use console output to print out the winner and the net amount owed by each player.
This code demonstrates how to handle input and output in a Kotlin program using appropriate user prompts and console output.



Session 5 Monday March 6
Session 5 Topics
0
Topic
Notes
1
Working with UML Diagrams. Analyzing and designing KOTLIN CODE with UML Forward generating a KOTLIN program from UML There are 2 ways to join KOTLIN classes together to create a community of objects Shared Field Composition of Kotlin Classs
Open
2
What is a constructor? Overloaded constructors Method overloading and overriding
Open
3
how to use enums String Representation of a KOTLIN class with toString()
Open
4
Open
There are no rows in this table
Unified Modeling Language (UML) is a graphical language used to design and visualize software systems [
]. JVM developers working with Kotlin code can use UML diagrams for their Kotlin classes, much like they would for Java classes, to better understand and document the structure and behavior of their software system [
]. In Kotlin, UML diagrams can be generated using tools like SimpleUMLCE, which allow for the decompilation of Kotlin bytecode into Java code that can then be visualized as a UML diagram.
UML diagrams can be used to model and document the structure of Kotlin classes, including their attributes, methods, and relationships with other classes. They can also be used to model the behavior of the system, including use case diagrams, sequence diagrams, and state diagrams. UML is a powerful tool for communication and collaboration among software developers and stakeholders, as it allows for a common understanding of the system being developed.


Constructors
A constructor is a special member function that is invoked when an object of the class is created primarily to initialize variables or properties.
A class needs to have a constructor and if we do not declare a constructor, then the compiler generates a default (no args) constructor.
Kotlin has two types of constructors –
Primary Constructor
Secondary Constructor
A class in Kotlin can have at most one primary constructor, and one or more secondary constructors.
The primary constructor initializes the class, while the secondary constructor is used to initialize the class and introduce some extra logic.
Primary Constructor –

image.png
The primary constructor is initialized in the class header, goes after the class name, using the constructor keyword. The parameters are optional in the primary constructor.
class Add constructor(val a: Int, val b: Int) {
// code
}
The constructor keyword can be omitted if there is no annotations or access modifiers specified.
class Add(val a: Int, val b: Int) {
// code
}
Illustrate the Primary Constructor –
//main function
fun main(args: Array<String>)
{
val add = Add(5, 6)
println("The Sum of numbers 5 and 6 is: ${add.c}")
}
//primary constructor
class Add constructor(a: Int,b:Int)
{
var c = a+b;
}
Output:
The Sum of two numbers is: 11
Explanation: When we create the object add for the class then the values 5 and 6 passes to the constructor.
The constructor parameters a and b initialize with the parameters 5 and 6 respectively. The local variable c contains the sum of variables. In the main, we access the property of constructor using ${add.c}.
Primary Constructor with Initializer Block –
The primary constructor cannot contain any code, the initialization code can be placed in a separate initializer block prefixed with the init keyword. ​Kotlin program of primary constructor with initializer block –
what is init block?
It acts as an initialiser block where member variables are initialised. This block gets executed whenever an instance of this class is created.
There can be multiple init blocks and they are called in the order they are written inside the class.
Note : init blocks gets called before the constructor of this class is called.
class Person (val _name: String) {
// Member Variables
var name: String
// Initializer Blocks
init{
println("This is first init block")
}
init{
println("This is second init block")
}
init{
println("This is third init block")
}
init {
this.name = _name
println("Name = $name")
}
}
fun main(args: Array<String>) {
val person = Person("Geeks")
}
Output:
This is first init block
This is second init block
This is third init block
Name = Geeks
Explanation: When the object person is created for the class Person, the value “Mahmood” is passed to the parameters name of the constructor. Two properties are declared in the class id and name.
Initializer block is executed at the time of object creation, and not only initializes the properties but also prints to the standard output.
Default value in primary constructor –
Similar to function default values in functions, we can initialize the constructor parameters with some default values.
Illustrate the use of default values in primary constructor –
fun main(args: Array<String>) {
val emp = employee(18018, "Sagnik")
// default value for emp_name will be used here
val emp2 = employee(11011)
// default values for both parameters because no arguments passed
val emp3 = employee()
}
class employee(emp_id : Int = 100 , emp_name: String = "abc") {
val id: Int
var name: String
// initializer block
init {
id = emp_id
name = emp_name
print("Employee id is: $id, ")
println("Employee name: $name")
println()
}
}
Output:
Employee id is: 18018, Employee name: Sagnik

Employee id is: 11011, Employee name: abc

Employee id is: 100, Employee name: abc
Explanation: Here, we have initialized the constructor parameters with some default values emp_id = 100 and emp_name = “abc”. When the object emp is created we passed the values for both the parameters so it prints those values. But, at the time of object emp2 creation, we have not passed the emp_name so initializer block uses the default values and print to the standard output.

Generating Anonymous Objects.
class MyObject(val id: Int) {
// add any properties or methods you need for the object
}
fun main() {
val objects = mutableListOf<MyObject>()
for (i in 1..10) {
objects.add(MyObject(i))
}
// do something with the objects
}

Secondary Constructor –
As mentioned above, Kotlin may have one or more secondary constructors. Secondary constructors allow initialization of variables and allow to provide some logic to the class as well. They are prefixed with the constructor keyword.
Kotlin program of implementing secondary constructor-
Kotlin
//main function
fun main(args: Array<String>)
{
Add(5, 6)
}
//class with one secondary constructor
class Add
{
constructor(a: Int, b:Int)
{
var c = a + b
println("The sum of numbers 5 and 6 is: ${c}")
}
}
Output:
The sum of numbers 5 and 6 is: 11
Which secondary constructor will be called is decided by the compiler based on the arguments received. In the above program, we does not specify to invoke which constructor and compiler decides by itself.
Kotlin program of two secondary constructors in a class-
fun main(args: Array<String>) {
employee(18018, "Sagnik")
employee(11011,"Praveen",600000.5)
}
class employee {
constructor (emp_id : Int, emp_name: String ) {
var id: Int = emp_id
var name: String = emp_name
print("Employee id is: $id, ")