Mastering Kotlin - A Beginner's
Mastering Kotlin - A Beginner's
Mastering Kotlin helps readers quickly understand core concepts and then move
on to practical projects using the Kotlin programming language.
Back in the day, Java was the de facto choice for creating Android apps. How-
ever, since Google announced Kotlin as the new language of choice for building
Android applications, developers haven’t looked back.
Kotlin differs from Java in that it has assertive interfaces that help determine variables
and expressions classes, even if they’re not defined. Kotlin is a beautiful alternative
for modifying and identifying faults because it has a familiar and straightforward
syntax and programming structure. It comes with a sophisticated compiler that can
track automatic casts, allowing verification durations to be more efficient. Kotlin
also has simple signals that may be interpreted without any need for set parameters.
And Kotlin is easy to set up: all you need is a Kotlin component for Android Studio.
Kotlin developers are in high demand. As a Kotlin developer, you’ll be able to pur-
sue a variety of career routes, spanning fields such as mobile app dev, game dev,
game design, and even software development. Many well-known brands use Kotlin
in their software and projects. Naturally, it is a good idea to learn Kotlin, and this
is where Mastering Kotlin can be the right manual for you!
With Mastering Kotlin, learning Kotlin becomes an easy task, and learners can use
their skills to create innovative Kotlin apps.
The Mastering Computer Science series is edited by Sufyan bin Uzayr, a writer and
educator with over a decade of experience in the computing field.
Mastering Computer Science
Series Editor: Sufyan bin Uzayr
Edited by
Sufyan bin Uzayr
First Edition published 2023
by CRC Press
6000 Broken Sound Parkway NW, Suite 300, Boca Raton, FL 33487-2742
and by CRC Press
2 Park Square, Milton Park, Abingdon, Oxon, OX14 4RN
CRC Press is an imprint of Taylor & Francis Group, LLC
© 2023 Sufyan bin Uzayr
Reasonable efforts have been made to publish reliable data and information, but the author and
publisher cannot assume responsibility for the validity of all materials or the consequences of their use.
The authors and publishers have attempted to trace the copyright holders of all material reproduced in
this publication and apologize to copyright holders if permission to publish in this form has not been
obtained. If any copyright material has not been acknowledged please write and let us know so we may
rectify in any future reprint.
Except as permitted under U.S. Copyright Law, no part of this book may be reprinted, reproduced,
transmitted, or utilized in any form by any electronic, mechanical, or other means, now known or
hereafter invented, including photocopying, microfilming, and recording, or in any information
storage or retrieval system, without written permission from the publishers.
For permission to photocopy or use material electronically from this work, access www.copyright.com
or contact the Copyright Clearance Center, Inc. (CCC), 222 Rosewood Drive, Danvers, MA 01923,
978-750-8400. For works that are not available on CCC please contact mpkbookspermissions@tandf.
co.uk
Trademark Notice: Product or corporate names may be trademarks or registered trademarks and are
used only for identification and explanation without intent to infringe.
DOI: 10.1201/9781003311904
Typeset in Minion
by KnowledgeWorks Global Ltd.
Contents
Preface, xix
About the Author, xxi
Statement in Kotlin31
Multiple Statements in Kotlin32
Block in Kotlin32
Variable Scope in Nested Blocks33
CONCLUSION33
Internal Modifier56
Protected Modifier57
Overriding of Protected Modifier57
Constructor Visibility58
INHERITANCE IN KOTLIN58
Inheritance Use60
Primary Constructor for Kotlin Inheritance62
Secondary Constructor for Kotlin Inheritance63
Overriding Member Functions and Properties64
Calling the Superclass Implementation65
INTERFACES IN KOTLIN66
Interfaces Creating66
Default Methods and Default Values67
Interface Properties68
Interface Inheritance69
Implementation of Multiple Interfaces70
DATA CLASSES IN KOTLIN71
Data Class Creation Rules72
toString()72
copy()73
hashCode() and equals()75
KOTLIN SEALED CLASSES76
Sealed Class with When77
KOTLIN ABSTRACT CLASS78
Multiple Derived Classes81
ENUM CLASSES IN KOTLIN82
Enums Initializing83
Enums Properties and Methods83
Properties and Functions of the Enum Class84
Enums as Anonymous Classes85
Usage of When Expression with Enum Class86
Contents ◾ ix
NULL SAFETY107
Nullable and Non-Nullable Sorts in Kotlin108
Checking for the Null in Conditions109
Safe Call Operator(?.)110
run() Method111
Elvis Operator(?:)112
Not-Null Assertion (!!) Operator113
TYPE CHECKING AND SMART CASTING
IN KOTLIN113
Type Checking113
Using When Expression114
Smart Casting114
Use of !is Operator115
EXPLICIT TYPE CASTING IN KOTLIN116
Unsafe Cast Operator: as116
Safe Cast Operator: as?117
REGEX AND RANGES118
Regular Expressions in Kotlin118
Regex Functions119
RANGES IN KOTLIN122
(..) Operator122
rangeTo() Function123
downTo() Function124
Range Using forEach Loop124
CONCLUSION126
Set Indexing226
Set Basics226
Contains() and ContainsAll() Functions227
MUTABLESETOF() METHOD IN KOTLIN228
Adding and Deleting Elements from a Set229
Set Indexing229
Set the First and Last Element230
Traversal in a MutableSet230
Contains() and ContainsAll() Methods230
HASHSETOF() IN KOTLIN232
Adding and Deleting Elements from a HashSet 232
HashSet Traversal233
Indexing in a HashSet233
Contains() and ContainsAll() Functions233
MAPOF() in Kotlin234
Map Size235
Empty Map236
Get Map Values236
Map Contains Keys or Values237
Two Values and the Same Key237
HASHMAP IN KOTLIN238
HashMap Time Complexity241
ANNOTATIONS IN KOTLIN242
Using Annotation242
Declaring Annotation243
Annotate a Constructor243
Annotate a Property243
Several Built-in Annotations243
@Target 243
@Retention 244
@Repeatable 245
xvi ◾ Contents
REFLECTION IN KOTLIN245
Class References246
Function References246
Property References247
Constructor References248
OVERLOADING OF THE KOTLIN OPERATOR248
Unary Operators248
Increment and Decrement Operators249
Binary Operators250
Other Operators251
KOTLIN DESTRUCTURING DECLARATIONS251
Destructuring Declaration in Lambdas252
EQUALITY EVALUATION253
Structural Equality253
Referential Equality254
KOTLIN COMPARATOR255
Function255
Functions of Extension255
CONCLUSION259
fade in.xml272
fade_out.xml272
rotate.xml273
slide_down.xml273
slide_up.xml273
zoom_in.xml274
zoom_out.xml274
Create MainActivity.kt File275
AndroidManifest.xml File276
KOTLIN ANDROID FADE IN/OUT277
Modify activity_main.xml File277
Add an anim Folder278
Change the MainActivity.kt File279
AndroidManifest.xml File280
MENUS FOR ANDROID281
How Can We Define a Menu in an XML File?281
Different Sorts of Menus in Android282
Kotlin Progress Alerts for Android283
Take Note of Notification Channels283
STRUCTURE OF THE ANDROID PROJECT FOLDER286
Manifests Folder286
Java Folder287
Resource (res) Folder288
Gradle Scripts Folder289
CONCLUSION289
APPRAISAL, 291
BIBLIOGRAPHY, 299
INDEX, 303
Preface
The Mastering Computer Science series covers a wide range of topics, span-
ning programming languages as well as modern-day technologies and
frameworks. The series has a special focus on beginner-level content, and
is presented in an easy-to-understand manner, comprising:
The Mastering Computer Science series of books start from the core con-
cepts, and then quickly move on to industry-standard coding practices, to
help learners gain efficient and crucial skills in as little time as possible.
The books assume no prior knowledge of coding, so even absolute newbie
coders can benefit from this series.
The Mastering Computer Science series is edited by Sufyan bin Uzayr, a
writer and educator with more than a decade of experience in the comput-
ing field.
xix
About the Author
xxi
Chapter 1
Getting Started
IN THIS CHAPTER
➢➢ Introduction
➢➢ Environment setup
➢➢ Data types, variables, and operators
➢➢ Type conversion
➢➢ Standard input/output
Example:
fun main()
{
println("Hello Everyone");
}
DOI: 10.1201/9781003311904-1 1
2 ◾ Mastering Kotlin: A Beginner’s Guide
HISTORY OF KOTLIN
The following are significant landmarks in Kotlin’s history:
FEATURES OF KOTLIN
The following are major Kotlin features:
Multiplatform in Kotlin.
6 ◾ Mastering Kotlin: A Beginner’s Guide
• The language, essential libraries, and basic tools are all included
in Common Kotlin. Code written in common Kotlin runs on all
platforms.
• We may reuse multiplatform logic in standard and platform-specific
code with Kotlin Multiplatform libraries.
• Platform-specific Kotlin versions should use for interoperabil-
ity. Platform-specific Kotlin versions (Kotlin/JVM, Kotlin/JS, and
Kotlin/Native) provide language extensions and platform-specific
libraries and tools.
• We may access the platform’s native code (JVM, JS, and Native) and
use all native features through these platforms.
KOTLIN’S ARCHITECTURE
A well-designed architecture is essential for an application to scale its
features and match the end user base’s expectations. Kotlin has its own
unique and exclusive architecture for allocating memory and producing
high-quality results for developers and end users.
Kotlin’s coroutines and classes construct the core so that less boilerplate
code is produced, performance is increased, and efficiency is reinforced.
The Kotlin compiler can behave differently in several situations, particu-
larly when earmarking distinct types of languages.
Architecture in Kotlin.
The architectural design clearly shows that code execution takes three
simple phases.
When a pair of bytecoded files run on the JVM, they initiate mutual com-
munication, which is how the Kotlin feature known as interoperability for
Java came to be.
Kotlin to JavaScript transformation occurs when Kotlin targets
JavaScript.
When JavaScript is selected as the target, any Kotlin code part of
the library that sails Kotlin is then spilled with JavaScript. The Java
Development Kit (JDK) or any java library used, on the other hand, is not
included.
A non-Kotlin file is not considered during this process. While aiming
toward JavaScript, the Kotlin compiler converts the kt file into ES5.1 to
output consistent JavaScript code. The Kotlin compiler strives for optimal
output size, interoperability with existing modules, standard library func-
tionality, and JavaScript readable output.
The discussion has shown that Kotlin compilers may produce more effi-
cient, competent, and independent code, resulting in a high-performing
software product.
(Continued)
Getting Started ◾ 9
Kotlin Java
Variable data type specifications are not Variable data type specifications are required
required in Kotlin. in Java.
Kotlin supports lambda expression. Java does not support lambda expression.
Kotlin includes the Lazy-Loading Java does not support this functionality.
functionality.
Kotlin has language scripting capabilities; Java does not support language scripting.
we may use it directly in our Gradle
build scripts.
Kotlin supports contemporary Java supports the OOP’s paradigm.
programming notions like delegates,
extensions, and higher-order functions.
The annual pay range for “Kotlin” is The annual compensation for a java
around $107,275 for Software engineers developer is $104,793.
to $121,034 for Android Developers.
Frameworks in Kotlin/JS
Frameworks that make it easier to construct web apps are extremely useful
in modern web development. Here are some prominent web frameworks.
Kotlin/Native
Kotlin/Native is a technology that compiles Kotlin code to native binaries
that can operate without using a virtual machine. It is a native implemen-
tation of the Kotlin standard library and an LLVM-based backend for the
Kotlin compiler.
• macOS
• Linux
• iOS, tvOS, watchOS
• Android NDK
• Windows (MinGW)
14 ◾ Mastering Kotlin: A Beginner’s Guide
$kotlinc myfirstapp.kt
Run the program now to view the output in the command-line compiler:
$kotlin myfirstapp.kt
Hello, Everyone
The following are the specifics of the “Hello, Everyone” program:
Line 1: The first line is a remark that the compiler ignores. Comments
are made to programs to make the source code easier to understand for
readers.
Kotlin accepts two types of comments:
Every program begins with the main() function. All functions in Kotlin
begin with the fun keyword, followed by the function name (here main),
a list of parameters, an optional return type, and the function body
({.......}).
In this scenario, the parameter – an array of strings and return units –
is included in the main function. The unit type, which corresponds to void
in Java, indicates that the function does not return any value.
Line 3: The third line is a statement that writes “Hello, Everyone” to the
program’s standard output.
println("Hello, Everyone")
18 ◾ Mastering Kotlin: A Beginner’s Guide
Source Code:
fun main(args : Array<String>)
{
var myint = 34
//add suffix L for long integer
Let’s develop a program to represent the floating-point data type and its
minimum and maximum values.
Source Code:
// Kotlin code
fun main(args : Array<String>) {
var myfloat = 55F // add
suffix F for float
println("My float value ${myfloat}")
Source Code:
// Kotlin code
fun main(args : Array<String>){
if (true is Boolean){
print("Yes,true is a boolean value")
}
}
Source Code:
// Kotlin code
fun main(args : Array<String>){
var alphabet: Char = 'D'
println("D is a character : ${alphabet is Char}")
}
VARIABLES IN KOTLIN
Every variable in Kotlin must define before it can utilize. An attempt to
use a variable without declaring it results in a syntax error. The declaration
of the variable type also determines the type of data that can store in the
memory location.
The type of variable in the case of local variables may deduce from the
initialized value.
var rollno = 54
var name = "Nidhi"
Getting Started ◾ 21
println(roll-no)
println(name)
Above is the local variable roll-no, whose value is 54 and whose type is
Integer because the literal type is int, and another variable, name, whose
type is String.
Variables in Kotlin are declared using one of two kinds:
var myAge = 26
myAge = 27 // compiles successfully
println("My new Age is ${myAge}")
Variable Scope
A variable exists just within the code block({............}) where it was defined.
Outside of the loop, we cannot access the variable. The same variable can
declare inside the nested loop – for example, if a function has an argument
x and we create a new variable x inside the same loop, then the variable x
inside the loop is different from the argument.
22 ◾ Mastering Kotlin: A Beginner’s Guide
Naming Convention
LowerCamelCase should be used to name all variables.
OPERATORS IN KOTLIN
Operators are special symbols that carry out various operations on oper-
ands. For example, + and – are addition and subtraction operators, respec-
tively. Kotlin, like Java, has a variety of operators:
• Arithmetic operator
• Relation operator
• Assignment operator
• Unary operator
• Logical operator
• Bitwise operator
Arithmetic Operator
Operators Meaning Expression Translate to
+ Addition c+d c.plus(d)
– Subtraction c–d c.minus(d)
* Multiplication c*d c.times(d)
/ Division c/d c.div(d)
% Modulus c%d c.rem(d)
Source Code:
fun main(args: Array<String>)
{
var c = 20 var d = 4 println("c + d = " + (c + d))
println("c - d = " + (c - d))
println("c * d = " + (c.times(d)))
println("c / d = " + (c / d))
println("c % d = " + (c.rem(d)))
}
Getting Started ◾ 23
Relation Operator
Operators Meaning Expression Translate to
> greater than c>d c.compareTo(d) > 0
< less than c<d c.compareTo(d) < 0
>= greater than or equal to c >= d c.compareTo(d) >= 0
<= less than or equal to c <= d c.compareTo(d) <= 0
== is equal to c == d c?.equals(d)? : (d === null)
!= not equal to c != d !(c?.equals(d)? : (d === null)) > 0
Source Code:
fun main(args: Array<String>)
{
var a = 20
var b = 10
println("a > b = "+(a>b))
println("a < b = "+(a.compareTo(d) < 0))
println("a >= b = "+(a>=b))
println("a <= b = "+(a.compareTo(b) <= 0))
println("a == b = "+(a==b))
println("a != b = "+(!(a?.equals(b)?: (b ===
null))))
}
Assignment Operator
Operators Expression Translate to
+= c=c+d c.plusAssign(d) > 0
−= c=c–d c.minusAssign(d) < 0
*= c=c*d c.timesAssign(d) >= 0
/= c=c/d c.divAssign(d) <= 0
%= c=c%d c.remAssign(d)
Source Code:
fun main(args : Array<String>){
var c = 10
var d = 5
c+=d
println(c)
c-=d
println(c)
24 ◾ Mastering Kotlin: A Beginner’s Guide
c*=d
println(c)
c/=d
println(c)
c%=d
println(d)
}
Unary Operator
Operators Expression Translate to
++ ++c or c++ c.inc()
— –c or c– c.dec()
Source Code:
fun main(args : Array<String>){
var c=10
var flag = true
println("First print then increment: "+ c++)
println("First increment then print: "+ ++c)
println("First print then decrement: "+ c--)
println("First decrement then print: "+ --c)
}
Logical Operator
Operators Meaning Expression
&& return true if all expressions are true (c>d) && (c>a)
|| return true if any expression is true (c>d) || (c>a)
! return complement of the expression c.not()
Source Code:
fun main(args : Array<String>){
var a = 110
var b = 24
var c = 11
var result = false
if(a > b && a > c)
println(a)
if(a < b || a > c)
println(y)
Getting Started ◾ 25
if( result.not())
println("Logical operators")
}
Bitwise Operator
Operators Meaning Expression
Shl signed shift left c.shl(d)
Shr signed shift right c.shr(d)
Ushr unsigned shift right c.ushr()
And bitwise and c.and(d)
Or bitwise or c.or()
Xor bitwise xor c.xor()
Inv bitwise inverse c.inv()
Source Code:
fun main(args: Array<String>)
{
println("4 signed shift left by 1 bit: " +
4.shl(1))
println("11 signed shift right by 2 bits: : "
+ 11.shr(2))
println("15 unsigned shift right by 2 bits: "
+ 15.ushr(2))
println("35 bitwise and 21: " + 35.and(21))
println("35 bitwise or 21: " + 35.or(21))
println("35 bitwise xor 21: " + 35.xor(21))
println("13 bitwise inverse is: " + 13.inv())
}
output. We can output any of the data types integer, float, and any patterns
or texts on the system’s screen.
To display output on the screen, use any of the following functions:
print() function
println() function
Source Code:
fun main(args: Array<String>)
{
print("Hello, Everyone ")
println("This is tutorial of Kotlin.")
}
print("Kotlin - ")
print("A Computer Science portal for Kotlin")
}
var a = 20
var b = 30
var c = 40L
var marks = 50.4
println("Sum of {$c} and {$d} is : ${sum(c,d)}")
println("Long value is: $e")
println("marks")
println("$marks")
}
Input of Kotlin
The core action done by Kotlin standard input is to flow byte streams from
an input device, such as a keyboard, to the system’s main memory.
We may obtain user input by using the following function:
readline() method
Scanner class
import java.util.Scanner;
Create an instance for the scanner class and receive user input. In the fol-
lowing application, we will demonstrate how to accept integer, float, and
Boolean data types input.
import java.util.Scanner
fun main(args: Array<String>)
{
// create an object for scanner class
val number1 = Scanner(System.'in')
28 ◾ Mastering Kotlin: A Beginner’s Guide
Source Code:
fun main(args: Array<String>) {
print("Enter Integer value: ")
val string1 = readLine()!!
//.toInt() function converts the string into
Integer
var integerValue: Int = string1.toInt()
println("We entered: $integerValue")
print("Enter double value: ")
val string2= readLine()!!
//.toDouble() function converts the string
into Double
var doubleValue: Double = string2.toDouble()
println("We entered: $doubleValue")
}
Getting Started ◾ 29
In Kotlin, a helper function can be used to convert one data type to another
explicitly.
Example:
var myNumber = 110
var myLongNumber: Long = myNumber.toLong()
• toShort()
• toByte()
• toInt()
• toFLoat()
• toLong()
• toChar()
• toDouble()
30 ◾ Mastering Kotlin: A Beginner’s Guide
Source Code:
fun main(args: Array<String>)
{
Source Code:
fun sumOf(a:Int,b:Int): Int{
return a+b
}
Kotlin if Expression
“If” is a statement in Java but an expression in Kotlin. It is referred to as an
expression since it compares the values of c and d and returns the greatest
value. As a result, is there no ternary operator (c>d)?c:d in Kotlin, because
the if expression replaces.
if(condition) condition met, else condition doesn’t meet.
Source Code:
fun main(args: Array<String>){
val c = 1100
val c = 989
var e = 1022
var max1 = if(c > d) c else d
var max2 = if(e > c) e else c
println("The maximum of ${c} and ${d} is $max1
" )
println("The maximum of ${e} and ${c} is $max2
" )
}
Statement in Kotlin
A statement is a syntactic unit in any programming language that describes
an action to be performed. A program is made up of a series of one or more
32 ◾ Mastering Kotlin: A Beginner’s Guide
Source Code:
fun main(args: Array<String>){
val sum: Int
sum = 110
println(sum) // single
statement
println("Hello");println("Everyone") //
Mutilple statements
}
Block in Kotlin
A block is a section of software code enclosed by curly braces ({..}). A block
can be made up of one or more statements, each preceded by variable dec-
larations. A block contains one or more nested blocks. Every function has
its own block, and the main function likewise has one.
CONCLUSION
This chapter covered an overview of Kotlin, including how to set up a com-
mand-line environment and integrate it with Intellij. We also covered fun-
damental programming in Kotlin and data types, variables, and operators.
In addition, we discussed Standard input-output in Kotlin. The last section
discussed type conversion, expressions, statements, and blocks in Kotlin.
Chapter 2
Object-Oriented
Programming (OOP)
Concepts
IN THIS CHAPTER
Class
Class, like Java, is a blueprint for objects with comparable features. Before
creating an object, we must first specify a class, and the class keyword is
used to do so.
The class declaration comprises the class name, the class header, and the
class body, all enclosed by curly braces.
Syntax:
class class-Name
{ // class header
// property
// member-function
}
The header and class body are optional; if there is nothing between the
curly braces, the class body can be removed.
class emptyClass
Object
It is an OOP core unit that represents real-world items with state and
behavior. Objects are used to access a class’s attributes and member func-
tions. Multiple instances of the same class can create in Kotlin. An item is
made up of:
obj.nameOfProperty
obj.funtionName(parameters)
38 ◾ Mastering Kotlin: A Beginner’s Guide
Kotlin program for creating many objects and accessing the class’s
properties and member functions:
class employee
{// Constructor Declaration of Class
var name: String = ""
var age: Int = 0
var gender: Char = 'F'
var salary: Double = 0.toDouble()
fun insertValues(n: String, a: Int, g: Char, s:
Double) {
name = n
age = a
gender = g
salary = s
println("Name of the employee: $name")
println("Age of the employee: $age")
println("Gender: $gender")
println("Salary of the employee: $salary")
}
fun insertName(n: String) {
this.name = n
}
}
fun main(args: Array<String>) {
// creating multiple objects
var obj = employee()
// object 2 of class employee
var obj2 = employee()
}
Object-Oriented Programming (OOP) Concepts ◾ 39
Syntax:
class outClass {
............
// properties of the outer class or a member
function
class nestClass {
..........
// properties of the inner class or
member function
}
}
Note that nested classes cannot access the members of the outer class, but
we may access nested class properties from the outer class without gener-
ating an object for the nested class.
Program of accessing nested class attributes in Kotlin:
In Comparison to Java
When it comes to features and use cases, Kotlin classes are quite close to
Java classes but not identical. The Nested class in Kotlin is analogous to a
static nested class in Java, whereas Inner class is comparable to a non-static
nested class in the Java.
Kotlin Java
Nested class Static Nested class
Inner class Non-Static class
Object-Oriented Programming (OOP) Concepts ◾ 41
In the following program, we attempt to access str from the inner class mem-
ber function. However, it does not work and generates a compile-time error.
First, put the inner keyword before the inner class. Then, make an instance
of the outer class; otherwise, we won’t be able to utilize inner classes.
Syntax:
var <propertyName>[: <PropertyType>]
[= <property_initializer>]
[<getter>]
[<setter>]
The property initializer, getter, and setter are all optional in this case.
If the property type can infer from the initializer, we may also omit it.
Object-Oriented Programming (OOP) Concepts ◾ 43
class company
{
var names: String = "Defaultvalue"
}
class company
{
var names: String = "defaultvalue"
get() = field // getter
set(value) { field = value } // setter
}
obtain a field because the code get() = field. Using the dot(.) syntax, we may
acquire or set the properties of a class object.
val d = company()
d.names = "Hubtutor" // access setter
println(d.names) // access getter
Private Modifier
If we want the get method available to the public, we may use the follow-
ing code:
var names: String = ""
private set
Object-Oriented Programming (OOP) Concepts ◾ 45
Because of the private modifier near the set accessor, we can only set the
name in a method within the class. A method within a class is used in a
Kotlin application to set the value.
class company () {
var names: String = "abc"
private set
println("${hub.email_id}")
geek.email_id = "[email protected]"
println("${hub.email_id}")
println("${hub.password}")
println("${hub.age}")
println("${hub.gender}")
// throw IllegalArgumentException("Passwords is
small")
geek.password = "abc"
// throw IllegalArgumentException("Age should be
18+")
geek.age= 5
// throw IllegalArgumentException("User should be
male")
geek.gender = 'M'
}
accessor methods – a getter and a setter – are supplied to allow the data
to be accessed by the users of the specified class. Additional logic is imple-
mented in the setter for delivering change notifications and verifying the
passed value.
Property
In the case of Java, it is a mixture of accessories and fields. Properties
are intended to be first-class language features in Kotlin. These features
have taken the place of fields and accessor methods. A class property is
declared in the same way as a variable, using the val and var keywords. A
var-declared property is mutable and hence changeable.
Creating a class:
class Abcd(
val names: String,
val ispassed: Boolean
)
class Abcd(
val names: String,
val ispassed: Boolean
)
/*
In Java
Abcd abcd = new Abcd("Bobi",true);
48 ◾ Mastering Kotlin: A Beginner’s Guide
System.out.println(person.getName());
System.out.println(person.isMarried());
*/
}
The constructor in Kotlin can be invoked without the need for a new key-
word. Instead of using the getter, the property is directly addressed. The
logic is same, but the code is significantly shorter. Setters of mutable prop-
erties operate identically.
Customer Accessors
Property accessor implementation on a custom basis:
class Rectanglee(val height: Int, val width: Int)
{
val isSquare: Boolean
get() {
return height == width
}
}
The property is Square does not require a field to contain the value. It just
has a custom getter with the given implementation. The value is calculated
each time the property is accessed.
KOTLIN CONSTRUCTOR
A constructor is a specific member function called when a class object
is formed to initialize variables or attributes. A constructor is required
for every class, and if we do not specify one, the compiler will build one
for us.
There are two kinds of constructors in Kotlin:
• Primary Constructor
• Secondary Constructor
Object-Oriented Programming (OOP) Concepts ◾ 49
In Kotlin, a class can have one primary constructor and more subsidiary
constructors. The primary constructor is responsible for initializing the
class, whereas the secondary constructor is responsible for initializing the
class and introducing some extra logic.
Primary Constructor
After the class name, the constructor keyword is used to initialize the
primary constructor in the class header. The arguments in the main con-
structor are optional.
//main function
fun main(args: Array<String>)
{
val add = Add(6, 8)
println("The Sum of numbers 6 and 8 is: ${add.c}")
}
//primary constructor
class Add constructor(c: Int,d:Int)
{
var a = c+d;
}
Explanation: When we build the class’s object add, the numbers 6 and 8
are sent to the constructor. The constructor arguments a and b are initially
set to 6 and 8, respectively.
The total of variables is stored in the local variable a. In the primary
function, we use $add.a to access the constructor property.
50 ◾ Mastering Kotlin: A Beginner’s Guide
// initializer block
init {
id = emp_id
names = emp_names
Explanation: When the object emp is formed for the class employee, the
values 18118 and “Sanik” are supplied to the constructor’s arguments emp
id and emp names. The class id and names declare two attributes.
When an object is created, the initializer block is called, which initial-
izes the attributes and prints to the standard output.
The default value in the primary constructor: We may initialize the
constructor parameters with some default values, similar to initializing
functions’ default values.
In the main constructor of a Kotlin program, the following default
values are used:
// initializer block
init {
id = emp_id
name = emp_name
Secondary Constructor
As previously stated, Kotlin may have one or more secondary construc-
tors. Secondary constructors allow for variable initialization and the addi-
tion of logic to the class. The keyword constructor precedes them.
Program of Kotlin implementation of a secondary constructor:
//main function
fun main(args: Array<String>)
{
Add(8, 6)
}
//class with one secondary constructor
class Add
{
constructor(c: Int, d:Int)
52 ◾ Mastering Kotlin: A Beginner’s Guide
{
var a = c + d
println("The sum of numbers 8 and 6 is: ${a}")
}
}
//main function
fun main(args: Array<String>)
{
Add(51, 61)
Add(51, 61, 71)
Object-Oriented Programming (OOP) Concepts ◾ 53
//main function
fun main(args: Array<String>)
{
Add(51,61)
}
class Add {
// calling another secondary using this
constructor(c: Int,d:Int) : this(c,d,71) {
var sumOfTwo = c + d
println("The sum of two numbers 51 and 61 is:
$sumOfTwo")
}
// this executes first
54 ◾ Mastering Kotlin: A Beginner’s Guide
Calling the secondary constructor of the parent class from the secondary
constructor of the child class: using the super keyword, we may call the
parent class’s secondary constructor from the child class’s secondary con-
structor. We demonstrated the calling procedure below.
fun main(args: Array<String>) {
Child(18118, "Sanik")
}
open class Parent {
constructor (emp_id: Int, emp_name: String, emp_
salary: Double) {
var id: Int = emp_id
var name: String = emp_name
var salary : Double = emp_salary
println("Employee id is: $id")
println("Employee name: $name")
println("Employee salary: $salary")
println()
}
}
class Child : Parent {
constructor (emp_id : Int, emp_name:
String):super(emp_id,emp_name,5000.55){
var id: Int = emp_id
var name: String = emp_name
println("Employee id is: $id")
println("Employee name: $name")
}
}
Modifier Description
Public Visible everywhere
Private Visible inside the same class only
Internal Visible inside the same module
Protected Visible inside the same class and its subclasses
Public Modifier
The default modifier in Kotlin is public. It is the most often used modi-
fier in the language, and there are extra limits on who may view the
part being modified. Unlike Java, there is no need to define anything
as public in Kotlin – it is the default modifier if no other modifier is
declared – public works the same in Kotlin as it does in Java. When the
public modifier is applied to top-level items – classes, methods, or vari-
ables defined directly within a package – any other code can access them.
If the public modifier is applied to a nested element – an inner class or
function within a class – then any code that can access the container may
also access this element.
// by default public
class C {
var int = 20
}
Classes C and D are available from anywhere in the code, and the vari-
ables int and int2 and the method display() are accessible from everything
that can access classes C and D.
56 ◾ Mastering Kotlin: A Beginner’s Guide
Private Modifier
Private modifiers in Kotlin restrict access to code defined inside the same
scope. It prevents access to the modifier variable or function from being
available outside of the scope. Unlike Java, Kotlin enables several top-level
declarations in the same file – a private top-level element in the same file
can be accessible by everything else in the same file.
In this case, class C can only access from within the same source file, and the
int variable can only be accessed from within class C. When we attempted
to access int from outside the class, we met with a compile-time error.
Internal Modifier
The internal modifier is a newly introduced modifier in Kotlin that Java does
not support. Internal signifies that it will only be available in the same mod-
ule; attempting to access the declaration from another module will result in
an error. A module is a collection of files that have been built together.
internal class C {
}
public class D {
internal val int = 20
internal fun display() {
}
}
Object-Oriented Programming (OOP) Concepts ◾ 57
Class C is only available from inside the same module in this case. Even
though class D may be accessed everywhere, the variable int and method
display() are only available inside the same module.
Protected Modifier
The protected modifier in Kotlin only enables access to the declaring class
and its subclasses. At the top level, the protected modifier cannot be dis-
closed. We used the derived class’s getvalue() function to retrieve the int
variable in the following example.
// base class
open class C {
// protected variable
protected val int = 20
}
// derived class
class D: C() {
fun getvalue(): Int {
// accessed from the subclass
return int
}
}
// base class
open class C {
// protected variable
open protected val int = 20
}
58 ◾ Mastering Kotlin: A Beginner’s Guide
// derived class
class D: C() {
override val int = 30
fun getvalue():Int {
// accessed from the subclass
return int
}
}
Constructor Visibility
Constructors are always public by default, but modifiers may adjust their
visibility.
INHERITANCE IN KOTLIN
One of the most significant aspects of OOP is inheritance. Inheritance
allows for code reuse by allowing all of the features of an existing class
(base-class) to be inherited by a new class (derived-class). Furthermore,
the derived class can add its features.
Syntax:
open class base-Class (x:Int ) {
..........
}
Object-Oriented Programming (OOP) Concepts ◾ 59
By default, all classes in Kotlin are final. We must apply the open key-
word in front of the base class to allow the derived class to inherit
from it.
Kotlin inheriting properties and methods from the base class: We
inherit all of its properties and functions when we inherit a class. We can
utilize the variables and functions from the base class in the derived class
and call functions from the derived class object.
//base class
open class base-Class{
val name = "Hubtutor"
fun C(){
println("Base Class")
}
}
//derived class
class derived-Class: base-Class() {
fun D() {
println(name) //inherit name
property
println("Derived class")
}
}
fun main(args: Array<String>) {
val derived = derived-Class()
derived.C() // inheriting the base class
function
derived.D() // calling derived class
function
}
Explanation: There is a base class and a derived class in this case. When
we instantiate the derived class, we generate an object, which is then
utilized to call the base and derived class functions. The derived.C()
function is used to invoke the C() function, which prints “Base Class.”
The derived.D() method is used to invoke the function D(), which prints
60 ◾ Mastering Kotlin: A Beginner’s Guide
the variable name inherited from the base class as well as the “Derived
class.”
Inheritance Use
Assume a corporation has three employees: a webDeveloper, an iOS-
Developer, and an AndroidDeveloper. They all have certain charac-
teristics in common, such as a name and an age and some unique
abilities.
First, we divide the individuals into three classes, and each class has
certain common and specific skills.
All three developers have the same name and age, but their programming
skills are very different. We would be replicating the identical code for
each character’s name and age in each class.
If we wish to add a salary() function, we must duplicate the code in all
three classes. This results in several duplicate copies of code in our pro-
gram, which will almost certainly result in more complicated and chaotic
code.
The work is made more accessible by employing inheritance. We may
construct a new base class Employee that contains the features shared by
the three original types. These three classes can then inherit common
characteristics from the basic class and add their unique features. We can
easily add the salary functionality to the Employee class without creating
duplicates.
Object-Oriented Programming (OOP) Concepts ◾ 61
In this case, webDeveloper inherits all of the features from the base class
and its feature website(). The same for the other two classes: iosDeveloper
and androidDeveloper. It improves the readability and extensibility of our
code.
Kotlin inheritance program:
//base-class
open class Employees( names: String,age: Int,salary :
Int) {
init {
println("Name is $names, $age years old and
earning $salary per month. ")
}
}
//derived-class
class webDevelopers( names: String,age: Int,salary :
Int): Employees(names, age,salary) {
fun website() {
println("website-developer")
println()
}
}
//derived-class
class androidDeveloper( names: String,age: Int,salary
: Int): Employees(names, age,salary) {
fun android() {
println("android app developer")
62 ◾ Mastering Kotlin: A Beginner’s Guide
println()
}
}
//derived class
class iosDevelopers( names: String,age: Int,salary :
Int): Employees(names, age,salary) {
fun iosapp() {
println("iOS app developer")
println()
}
}
//main method
fun main(args: Array<String>) {
val wd = webDevelopers("Genna", 28, 12000)
wd.website()
val ad = androidDevelopers("Gautam", 29,14000)
ad.android()
val iosd = iosDevelopers("Praniti", 22,18000)
iosd.iosapp()
}
//base-class
open class Employees(names: String,age: Int) {
init{
println("The name of Employee is $name")
println("The Age of an Employee is $age")
}
}
// derived-class
class CEO( names: String, age: Int, salary: Double):
Employees(names,age) {
init {
println("The Salary per annum is $salary crore
rupees")
}
}
fun main(args: Array<String>) {
CEO("Suniti Pichai", 40, 420.00)
}
Explanation: In this case, we instantiate the derived class CEO and supply
the parameters name, age, and salary. The derived class’s local variables
are initialized with the appropriate values, and the variable name and age
are sent as arguments to the Employee class.
The employees class outputs the variable names and values to standard
output before returning control to the derived class. The derived class then
terminates after executing the println() command.
//base class
open class Employees {
constructor(names: String,age: Int){
println("The Name of Employee is $name")
println("The Age of Employee is $age")
}
}
64 ◾ Mastering Kotlin: A Beginner’s Guide
// derived class
class CEO : Employees{
constructor( names: String,age: Int, salary:
Double): super(names,age) {
println("The Salary per annum is $salary
million dollars")
}
}
fun main(args: Array<String>) {
CEO("Sunidhi Nadela", 49, 220.00)
}
Explanation: We instantiate the class CEO and give the argument val-
ues to the secondary constructor in this case. It will initialize the local
variables and use super to pass them to the base class Employees (name,
age).
// base class
open class Animals {
open fun run() {
println("The Animals can run")
}
}
// derived class
class Tiger: Animals() {
override fun run() { // it overrides the run
method of base class
println("The Tiger can run very fast")
}
}
fun main(args: Array<String>) {
val t = Tiger()
t.run()
}
Object-Oriented Programming (OOP) Concepts ◾ 65
Similarly, we may override the base class’s property in the derived class.
Program of overriding the member property in Kotlin:
// base class
open class Animals {
open var name: String = "Dog"
open var speed = "50 km/hr"
}
// derived class
class Tiger: Animals() {
override var name = "Tiger"
override var speed = "120 km/hr"
}
fun main(args: Array<String>) {
val d = Tiger()
println(d.name+" can run at speed "+d.speed)
}
// base class
open class Phones() {
var color = "White Gold"
fun displayCompany(name:String) {
println("The Company is: $name")
}
}
// derived class
class iphone: Phones() {
fun displayColor(){
INTERFACES IN KOTLIN
Interfaces are Kotlin provided custom types that cannot be instantiated
directly. Instead, these describe a type of behavior that the implementing
types must follow. The interface allows us to create a collection of attri-
butes and methods that concrete types must follow and implement.
Interfaces Creating
The interface declaration in Kotlin starts with the interface keyword, then
the name of the interface, and finally the curly brackets that contain the
interface’s members. The distinction is that the members will not have
their definition. The conforming types will offer these definitions.
Example:
interface Vehicles()
{
fun start()
fun stop()
}
interface Vehicles {
fun start()
fun stop()
}
{
println("The Car is started")
}
fun main()
{
val obj = Car()
obj.start()
obj.stop()
}
interface FirstInterface {
fun add(c: Int, d: Int = 6)
fun print()
{
println("This is a default method defined in
the interface")
}
}
class InterfaceDemo : FirstInterface {
override fun add(c: Int, d: Int)
68 ◾ Mastering Kotlin: A Beginner’s Guide
{
val a = c + d
println("Sum is $a")
}
fun main()
{
val obj = InterfaceDemo()
println(obj.add(6))
obj.print()
}
Interface Properties
Interfaces, like methods, can include attributes. However, because the
interface doesn’t have a state, they cannot be created, and hence there are
no underlying fields to keep their values. As a result, the interface’s fields
are either left abstract or given an implementation.
Example of interface properties:
interface InterfaceProperties {
val c : Int
val d : String
get() = "Helloo"
}
Object-Oriented Programming (OOP) Concepts ◾ 69
fun main()
{
val x = PropertiesDemo()
println(x.c)
println(x.d)
}
Interface Inheritance
In Kotlin, interfaces can inherit from other interfaces. When one interface
extends another, it can add its properties and methods, and the imple-
menting type must define all of the properties and methods in both inter-
faces. An interface can inherit from many interfaces.
An example of interface inheritance:
interface Dimensions {
val len : Double
val br : Double
}
fun main()
{
val obj = XYZ()
obj.area()
obj.perimeter()
}
interface InterfaceProperties {
val c : Int
val d : String
get() = "Helloo"
}
interface InterfaceMethods {
fun description()
}
Object-Oriented Programming (OOP) Concepts ◾ 71
• toString()
• copy()
• hashCode()
• equals()
72 ◾ Mastering Kotlin: A Beginner’s Guide
toString()
This function returns a string containing all of the data class’s arguments.
First Example:
fun main(args: Array<String>)
{
//declarion of a data class
data class man(val roll: Int,val name:
String,val height:Int)
val man1=man(1,"man",40)
For the automatically created functions, the compiler only uses the attri-
butes defined inside the primary constructor.
It does not include the properties declared in the body of class.
Second Example:
fun main(args: Array<String>)
{
//declarion of a data class
data class man(val name: String)
Object-Oriented Programming (OOP) Concepts ◾ 73
{
//the property declared in class body
var height: Int = 0;
}
val man1=man("manisha")
//class body properties must be assigned
uniquely
man1.height = 80
copy()
Sometimes we need to replicate an object and update some of its attributes
while keeping the others intact.
The copy() method is utilized in this scenario.
Copy() properties:
copy() Declaration:
Example:
fun main(args: Array<String>)
{
//declaring a data class
data class man(val name: String, val age: Int)
{
//property declared in class body
var height: Int = 0;
}
}
Object-Oriented Programming (OOP) Concepts ◾ 75
hashCode() Declaration:
hashCode() properties:
• Two hash codes specified twice on the same object will be equivalent.
• If two objects are equal according to the equals() function, the hash
codes given will be the same.
val hash1=man1.hashCode();
val hash2=man2.hashCode();
val hash3=man3.hashCode();
println(hash1)
println(hash2)
println(hash3)
}
76 ◾ Mastering Kotlin: A Beginner’s Guide
Explanation: Because man1 and man2 have the same object contents, they
are equal and have the same hash code values.
{
val obj = Demo.D()
obj.display()
It should be noted that all subclasses of the sealed class must specify in
the same Kotlin file. However, they do not have to be specified within the
sealed class; they can be defined where the sealed class is accessible.
Example:
//sealed class with single subclass defined inside
sealed class ABCD {
class X: ABCD(){...}
}
As demonstrated below, an abstract class can have both abstract and non-
abstract members:
//abstract class
abstract class Employee(val name: String,val
experience: Int) { // Non-Abstract
// Property
// Abstract Property (Must be overridden by
Subclasses)
abstract var salary: Double
// Non-Abstract Method
fun employeeDetails() {
println("Name of the employee: $name")
println("Experience in years: $experience")
println("Annual Salary: $salary")
}
}
80 ◾ Mastering Kotlin: A Beginner’s Guide
// derived class
class Engineer(name: String,experience: Int) :
Employee(name,experience) {
override var salary = 510000.00
override fun dateOfBirth(date:String){
println("Date of Birth is: $date")
}
}
fun main(args: Array<String>) {
val eng = Engineer("Praniti",3)
eng.employeeDetails()
eng.dateOfBirth("03 December 1996")
}
// abstract class
abstract class Calculators {
abstract fun cal(a: Int, b: Int) : Int
}
// addition of two numbers
class Add : Calculators() {
override fun cal(a: Int, b: Int): Int {
return a + b
}
}
// subtraction of two numbers
class Sub : Calculators() {
override fun cal(a: Int, b: Int): Int {
return a - b
}
}
// multiplication of two numbers
class Mul : Calculators() {
override fun cal(a: Int, b: Int): Int {
return a * b
}
}
fun main(args: Array<String>) {
var add: Calculators = Add()
var a1 = add.cal(5, 6)
82 ◾ Mastering Kotlin: A Beginner’s Guide
Enums Initializing
Enums in Kotlin, like Java enums, can have a constructor. Because enum
constants are Enum class objects, they may be initialized by supplying spe-
cific values to the primary constructor.
Here’s an example of how to assign colors to cards:
Methods:
• values: This function returns a list of all the enum class’s constants.
• valueOf(): This function returns the enum constant specified in
enum that matches the input string. If the constant is missing from
the enum, an IllegalArgumentException is produced.
FRIDAY,
SATURDAY,
SUNDAY
}
fun main()
{
// A simple demonstration of properties and
methods
for (day in DAY.values()) {
println("${day.ordinal} = ${day.name}")
}
println("${DAY.valueOf(" FRIDAY ")}")
}
companion object{
fun today(obj: DAY): Boolean {
return obj.name.compareTo("SATURDAY") == 0
|| obj.name.compareTo("SUNDAY") == 0
}
}
}
Object-Oriented Programming (OOP) Concepts ◾ 85
fun main(){
// A simple demonstration of properties and
methods
for(day in DAY.values()) {
println("${day.ordinal} = ${day.name} and is
weekend ${day.isWeekend}")
}
val today = DAY.MONDAY;
println("Is today a weekend ${DAY.today(today)}")
}
fun main(){
when(DAY.SUNDAY){
DAY.SUNDAY -> println("Today is Sunday")
DAY.MONDAY -> println("Today is Monday")
DAY.TUESDAY -> println("Today is Tuesday")
DAY.WEDNESDAY -> println("Today is Wednesday")
DAY.THURSDAY -> println("Today is Thursday")
DAY.FRIDAY -> println("Today is Friday")
DAY.SATURDAY -> println("Today is Saturday")
// Adding an else clause will generate a
warning
}
}
Explanation: In this case, a new function is attached to the class using dot
notation, with the function class Circle.perimeter() and a return type of
Double. An object is created to instantiate the class Circle in the primary
function, and the function is invoked using the println() statement. When
the member function is called, it returns the area of the circle, whereas the
extension function delivers the perimeter of the circle.
fun main(){
println((-6).abs())
println(6.abs())
}
Nullable Receiver
Extension functions can also be defined using the nullable class type.
When the check for null is added inside the extension function, the proper
value is returned.
A nullable receiver is an example of an extension function:
fun main(){
// An extension function as a nullable receiver
fun ABC?.output(){
if(this == null){
println("Null")
}else{
println(this.toString())
}
}
val x = ABC("Charch")
// Extension function called using an instance
x.output()
// Extension function called on null
null.output()
}
class myClass {
// the companion object declaration
companion object {
fun display(){
println("The Function declared in
companion object")
}
}
}
fun main(args: Array<String>) {
// invoking member function
val ob = myClass.display()
}
class myClass {
companion object {
//the member function of companion object
fun display(str :String) : String{
return str
}
}
}
// the extension function of companion object
fun myClass.Companion.abc(){
println("The Extension function of companion
object")
}
fun main(args: Array<String>) {
val ob = myClass.display("The Function declared in
companion object")
println(ob)
// invoking the extension function
val ob2 = myClass.abc()
}
Object-Oriented Programming (OOP) Concepts ◾ 91
KOTLIN GENERICS
Generics are useful features that enable us to build classes, methods, and
properties that are accessible using various data types while maintaining
compile-time type safety.
Creating parameterized classes: A generic type is a type-parameter-
ized class or function. We always use angle brackets () to define the type
parameter in the program.
The following is the definition of the generic class:
class myClass<D>(text: D) {
var name = text
}
Because Hubtutors has the type String, the compiler figures out that we are
discussing myclass<String>.
Advantages of generic:
VARIANCE
In contrast to Java, Kotlin makes arrays invariant by default. Generic
types, by extension, are invariant in Kotlin. The out and in keywords
might help with this. Invariance is the feature that prevents a standard
generic function/class that has already been created for a specific data type
from accepting or returning another data type. All additional data types
are supertypes of Any.
There are two kinds of variation:
We defined an OutClass class above that can return a value of type T. Then,
for the reference that is a supertype of it, we may allocate an instance of
the OutClass:
Note: If we did not utilize the out type in the preceding class, the next
statement will result in a compiler error.
The in Keyword
We may utilize the in keyword on the generic type to assign it to the refer-
ence of its subtype. The in keyword may only use on parameter type that
are consumed, not produced:
Note: If we did not utilize the in type in the preceding class, the following
sentence would result in a compiler error.
94 ◾ Mastering Kotlin: A Beginner’s Guide
COVARIANCE
Covariance states that substituting subtypes is permissible but not super-
types, i.e., the generic function/class may accept subtypes of the data type for
which it is already defined, for example, a generic class created for Number
can accept Int, while a generic class defined for Int cannot accept Number.
This may be implemented in Kotlin by using the out keyword as seen below:
CONTRACOVARIANCE
It is used to replace a supertype value in the subtypes, i.e., the generic func-
tion or class may accept supertypes of the data type it is already defined.
For example, a generic class defined for Number cannot take Int, while a
generic class defined for Int may accept Number. In Kotlin, it is accom-
plished using the in keyword as follows:
TYPE PROJECTIONS
It is feasible to copy all the members of an array of some type into an array
of Any type, but for the compiler to compile our code, we must annotate
the input argument with the out keyword. As a result, the compiler con-
cludes that the input argument can be a subtype of the Any type.
Kotlin program for copying array elements into another:
fun copy(from: Array<out Any>, to: Array<Any>) {
assert(from.size == to.size)
// copying (from) array to (to) array
for (c in from.indices)
to[c] = from[c]
// printing elements of array in which copied
for (c in to.indices) {
println(to[c])
}
}
fun main(args :Array<String>) {
val ints: Array<Int> = arrayOf(1, 2, 3,4)
val any :Array<Any> = Array<Any>(4) { "" }
copy(ints, any)
STAR PROJECTIONS
When we don’t know what sort of value we’re looking for and merely want
to print all the items of an array, we use the star(*) projection.
Program of using star projections in Kotlin:
// star projection in array
fun printArray(array: Array<*>) {
array.forEach { print(it) }
}
fun main(args :Array<String>) {
val name = arrayOf("Good","for","Good")
printArray(name)
}
CONCLUSION
This chapter covered OOP’s concept, where we learned class and object,
nested class, constructors, and inheritances. We also covered interfaces,
abstract class, and Generic Type in Kotlin.
Chapter 3
Exceptional Handling,
Null Safety, and
Regex and Ranges
IN THIS CHAPTER
Exceptions in Kotlin
Exceptions in Kotlin are only unchecked and may be detected only
at run time. All exception classes are descended from the Throwable
class.
To throw an exception object, we often use the throw-expression:
throw Exception("Throwme")
In the above program, we start the num variable with the value 20/0,
although we know that dividing by zero is not permitted in arithmetic.
When we try to run the application, an exception is thrown.
To address this issue, we must employ the try-catch block.
Exceptional Handling, Null Safety, and Regex and Ranges ◾ 99
println("After exception")
}
catch(c: Exception){
println(c)
}
finally{
println("can't ignore ")
}
}
Syntax:
try {
// the code that can throw exception
} catch(c: ExceptionName) {
// catch exception and handle it
}
import kotlin.ArithmeticException
try block. The catch block will catch an exception and run the println()
function.
Kotlin Try-Catch Block as an Expression
As we have already established, expressions always return a value. We may
utilize the Kotlin try-catch block as an expression in our software. The
expression’s return value will be either the final expression of the try block
or the last expression of the catch block. If there is an exception in the
function, the catch block returns the value.
Using try-catch as an expression in a Kotlin program:
fun test(c: Int, d: Int) : Any {
return try {
c/d
//println("The Result is: "+ c / d)
}
catch(e:Exception){
println(e)
"Divide by zero not allowed"
}
}
// main function
fun main(args: Array<String>) {
// invoke test function
var results1 = test(20,2 ) //execute try block
println(results1)
var results = test(20,0 ) // execute catch block
println(results)
}
We can combine the finally block with the try block and then omit the
catch block.
Syntax:
try {
//the code that can throw exception
} finally {
// code of finally block
}
In the preceding program, we utilized the try with finally block instead of
the catch block. In this case, the catch block does not handle the exception,
but executes the finally block.
Finally block with try-catch block Syntax:
try {
// the code that can throw exception
} catch(c: ExceptionName) {
// catch the exception and handle it.
} finally {
// code of finally block
}
println(int)
} catch (c: ArithmeticException) {
println(c)
} finally {
println("This block will always executes")
}
}
Syntax:
// the outer try block
try
{
Exceptional Handling, Null Safety, and Regex and Ranges ◾ 105
try {
for (i in numbers.indices) {
try {
var n = (0..4).random()
println(numbers[i+1]/n)
Keep in mind that this result is created for a random integer. Don’t worry
if we obtain a different result because our result will be determined by the
random number generated at that moment.
catch blocks for the various exceptions and the parent exception class in
the last catch block to handle all the remaining exceptions that are not
defined by catch blocks in the program.
Syntax:
try {
// the code may throw exception
} catch(c: ExceptionNameOne) {
// catch the exception one and handle it
} catch(c: ExceptionNameTwo) {
// it catch the exception two and handle it
}
import java.util.Scanner
object Tests {
@JvmStatic
fun main(args: Array<String>) {
val scn = Scanner(System.'in')
try {
val n = Integer.parseInt(scn.nextLine())
if (512 % n == 0)
println("$n is a factor of 512")
} catch (c: ArithmeticException) {
println(c)
} catch (c: NumberFormatException) {
println(c)
}
}
}
import java.lang.NumberFormatException
import java.util.Scanner
object Tests {
@JvmStatic
Exceptional Handling, Null Safety, and Regex and Ranges ◾ 107
NULL SAFETY
The goal of Kotlin’s type system is to remove the risk of null references
in code since it is a billion-dollar error. The NullPointerExceptions are
thrown by the program at runtime, resulting in the application or system
failure.
If we’ve ever written code in Java or another language that contains the
idea of a null reference, we’ve probably seen a NullPointerException. If
Kotlin compiler finds a null reference without executing any other state-
ments, it raises a NullPointerException.
The following are some of the probable sources of NullPointer
Exceptions:
Now, if we want to get the length of the string st1, it assures that it will not
throw an NPE; therefore, we can confidently say:
val l = st1.length
However, accessing the length of the string st2 is not safe, and the
compiler gives an error:
We may easily set null to a nullable type variable in this case. To retrieve
the length of the string, however, we should use the safe operator.
firstname?.toUpperCase()
is equivalent to:
if(firstname != null)
firstname.toUpperCase()
else
null
If value is not null, we may use the safe call operator with let(), also(), and run().
A let operator can use to execute an action only when a reference con-
tains a non-nullable value. The lambda expression included within the let
is only run if the variable firstName is not null.
Because the variable firstname is null in this case, the lambda expression
to convert the string to Upper Case letters is not executed.
Program of using let in Kotlin:
run() Method
To perform an operation on a nullable reference, Kotlin provides the run()
function. It appears to be quite similar to let(), but inside a function body,
the run() method runs only when this reference is used instead of a func-
tion parameter:
Elvis Operator(?:)
When original variable is null, the Elvis operator returns a non-null value
or a default value. In other words, if the left expression is not null, the elvis
operator returns it; otherwise, the right expression is returned. If the left-
hand side expression is discovered to be null, the right-hand side expres-
sion is evaluated.
is equivalent to:
for(attribute in employeeDetails) {
if (attribute is String) {
println("The Name is: $attribute")
} else if (attribute is Int) {
println("The Age is: $attribute")
} else if (attribute is Double) {
println("The Salary is: $attribute")
} else {
println("Not an attribute")
}
}
}
114 ◾ Mastering Kotlin: A Beginner’s Guide
Smart Casting
In Java and other programming languages, explicit type casting on the
variable is required before accessing its properties, while Kotlin uses
smart casting. When a variable is passed through a conditional opera-
tor, the Kotlin compiler automatically changes it to a specific class
reference.
Exceptional Handling, Null Safety, and Regex and Ranges ◾ 115
Smart type casting is one of the most exciting capabilities offered in Kotlin.
To verify the type of a variable, we use the is or ! is operator, and the com-
piler automatically casts the variable to the desired type, as seen below:
Smart casts do not operate if the compiler cannot ensure that the variable
will not change between the check and the usage. The following guidelines
regulate the use of smart casts:
• Except for local delegated properties, val local variables always works.
• val properties only work if the property is private or internal, or if the
check is done in the same module as the property is defined. Smart
casts do not work on open properties or properties with custom
getters.
• var local variables only work if the variable has not been modified
between the check and usage, is not captured in lambda that modi-
fies it, and is not a local delegated property.
• Because the variable can change at any time, var properties never
operate.
It is possible that we cannot cast a variable to the target type, and it throws
an exception at runtime, which is why it is called unsafe casting.
Exceptional Handling, Null Safety, and Regex and Ranges ◾ 117
class Regex
Constructors:
Properties:
Regex Functions
containsMatchIn(): This function returns a boolean indicating whether
our pattern is matched in the input.
fun main()
{
// A regex to match any string starting with the
letter 'a'
val pattern = Regex("^a")
println(pattern.containsMatchIn("abcd"))
println(pattern.containsMatchIn("bacd"))
}
find(): From the specified beginning index, this method returns the
first matched substring pertaining to our pattern in the input.
fun find(input: CharSequence, start_Index: Int): MatchResult?
This example will show how to use the find() method in Kotlin:
fun main()
{
// Regex to match "ll" in a string
val pattern1 = Regex("ll")
val ans : MatchResult? = pattern1.
find("HellooHelloo", 6)
println(ans?.value)
}
fun findAll(
input: CharSequence,
start_Index: Int
): Sequence
120 ◾ Mastering Kotlin: A Beginner’s Guide
This example will show how to use the findAll method in Kotlin:
fun main()
{
// A Regex to match a 3 letter pattern beginning
with ab
val pattern2 = Regex("ab.")
val ans1 : Sequence<MatchResult> = pattern2.
findAll("absfffgdbabc", 0)
// forEach loop used to display all matches
ans1.forEach()
{
matchResult -> println(matchResult.value)
}
println()
}
fun main()
{
//to tests the demonstrating entire string match
val pattern = Regex("h([ee]+)ks?")
println(pattern.matches("heeks"))
println(pattern.matches("heeeeeeeeeeks"))
println(pattern.matches("heeksforheeks"))
}
fun main()
{
// Tests demonstrating entire string match
var pattern = Regex("heeks?")
println(pattern.matchEntire("heeks")?.value)
println(pattern.matchEntire("heeeeeeeks")?.value)
pattern = Regex("""\D+""")
println(pattern.matchEntire("heeks")?.value)
println(pattern.matchEntire("heeks13245")?.value)
}
fun replaceFirst(
input: Char_Sequence,
replacement: String
): String
fun main()
{
// Tests demonstrating replacement functions
val pattern4 = Regex("xyzz")
// replace all xyzz with abcd in the string
println(pattern4.replace("xyzzxyzzzzzzzzz",
"abcd"))
// replace only first xyz with abc not all
println(pattern4.replaceFirst("xyzzddddddxyzz",
"abcd"))
println()
}
122 ◾ Mastering Kotlin: A Beginner’s Guide
split(): This function divides the input string into tokens based on the
parameter value.
This example will show how to use the split() method in Kotlin:
fun main()
{
// Tests demonstrating split function
val pattern = Regex("\\s+") // separate for
white-spaces
val ans : List<String> = pattern.split("This is a
class")
ans.forEach { word -> println(word) }
}
RANGES IN KOTLIN
The range in Kotlin is a set of finite values specified by endpoints. In Kotlin,
a range consists of a start, a stop, and a step. The start and finish points in
the Range are inclusive, and the step value is set to 1 by default.
The range is used with comparable kinds.
Range may create in three ways in Kotlin:
(..) Operator
It is the most basic approach to interact with range. It will generate a range
from start to finish that includes both the start and end values. It is the
rangeTo() function’s operator form. We may create ranges for integers and
characters by using the (..) operator.
In Kotlin, use the (..) operator to create an integer range program:
println(num)
}
}
rangeTo() Function
It is similar to the (..) operator. It will generate a range up to the value
specified as an argument. It is also used to create range for numbers and
characters.
Program of using the rangeTo() method in Kotlin to create an integer
range:
downTo() Function
It is the reverse of the rangeTo() or (..). It generates a range in decreasing
order, from larger to smaller numbers. This section will define ranges in
reverse order for both integers and characters.
Kotlin program with an integer range that uses the downTo()
function:
step(): The keyword step can use to create a step between values. It is
mainly used to give the space between two values in rangeTo(), downTo(),
or the (..) operator. The default value for step is 1; therefore, the step func-
tion cannot have a value of zero.
Exceptional Handling, Null Safety, and Regex and Ranges ◾ 125
fun main() {
val predefined = (15..20)
println("minimum value of the range is:
"+predefined.min())
println("maximum value of the range is:
"+predefined.max())
println("sum of all values of the range is:
"+predefined.sum())
println("average value of the range is:
"+predefined.average())
}
126 ◾ Mastering Kotlin: A Beginner’s Guide
CONCLUSION
In this chapter, we covered Exceptional handling with try, catch, throw,
and finally, and we also covered try block and multiple catch blocks.
Moreover, we learned about Null safety and Regex and Ranges in Kotlin.
Chapter 4
IN THIS CHAPTER
➢➢ If-else
➢➢ While, do-while
➢➢ For loop
➢➢ Labeled and unlabeled break
➢➢ Labeled and unlabeled continue
Chapter 3 covered expression handling, null safety, and regex and ranges.
In this chapter, we will cover the control flow statement in Kotlin.
• if expression
• if-else expression
If Statement
It is used to describe whether a block of statements should be executed or
not, i.e., if a given condition is true, then the statement or block of state-
ments should execute; otherwise, the statement or block of statements
should not run.
Syntax:
if(condition) {
// the code to run if condition is true
}
Flowchart:
Statement of if.
Control Flow Statements ◾ 129
Example:
fun main(args: Array<String>) {
var c = 3
if(c > 0){
print("Yes,the number is positive")
}
}
If-Else Statement
The if-else statement is made up of two blocks of statements. When the condi-
tion is true, the “if” statement is used to run the block of code, and when the
condition is false, the “else” statement is used to execute the block of code.
Syntax:
if(condition) {
// the code to run if condition is true
}
else {
// the code to run if condition is false
}
Flowchart:
Statement of if-else.
130 ◾ Mastering Kotlin: A Beginner’s Guide
Example:
fun main(args: Array<String>) {
var a = 7
var b = 13
if(a > b){
print("Number 7 is larger than 13")
}
else{
println("Number 13 is larger than 7")
}
}
all other statements are skipped until the end of the block. If none of the
conditions are met, the last else statement is performed by default.
Syntax:
if(first-condition)
{
// the code to run if condition is true
}
else if(second-condition)
{
// the code to run if condition is true
}
else
{
}
Flowchart:
Statement of if-else-if.
132 ◾ Mastering Kotlin: A Beginner’s Guide
import java.util.Scanner
fun main(args: Array<String>) {
// to create an object for scanner class
val reader = Scanner(System.'in')
print("Enter number: ")
Nested If Expression
Nested if statements are if statements that are nestled inside another if
statement. If the first condition is true, code the associated block to be
run, and then check for if condition nested in the first block, and if it is
also true, code the related block to be executed. It will continue till the last
condition is met.
Syntax:
if(condition1){
// code-1
if(condition2){
// code-2
}
}
Control Flow Statements ◾ 133
Flowchart:
Statement of nested-if.
The Kotlin program to find the greatest value among three integers
is shown below:
import java.util.Scanner
fun main(args: Array<String>) {
Flowchart:
Statement of while-loop.
Control Flow Statements ◾ 135
block only when the condition becomes true, the do-while loop performs
the code first and then evaluates the expression or test condition.
do {
// the code to run
{
while(condition)
Flowchart:
Statement of do-while-loop.
Control Flow Statements ◾ 137
do {
println("2 * $c = "+ numb * c)
c++
}while(c < 11)
}
for(item in collection) {
// the code to execute
}
The for loop in Kotlin is used to iterate over the following since they all
offer an iterator:
• Range
• String
138 ◾ Mastering Kotlin: A Beginner’s Guide
• Array
• Collection
Iterate over the range from top to down using downTo, and then
step 3:
• when as a statement
• when as an expression
the condition matches. If none of the branches satisfy the requirement, the
else branch is executed.
import java.util.Scanner;
fun main(args: Array<String>) {
var reader = Scanner(System.'in')
print("Enter largebody:")
var lbt = reader.next()
when(lbt) {
"Sun" -> println("The Sun is a Star")
"Moon" -> println("The Moon is a Satellite")
"Earth" -> println("The Earth is a planet")
else -> println("don't know anything")
}
}
import java.util.Scanner;
fun main(args: Array<String>) {
var reader = Scanner(System.'in')
print("Enter-name:")
var lbt = reader.next()
when(lbt) {
"Sun" -> println("The Sun is a Star")
"Moon" -> println("The Moon is a Satellite")
"Earth" -> println("The Earth is a planet")
}
}
import java.util.Scanner;
fun main(args: Array<String>) {
var reader = Scanner(System.'in')
print("Enter the month of number:")
var monthyear = reader.nextInt()
var months = when(monthyear)
{
1->"Jan"
2->"Feb"
3->"March"
4->"April"
5->"May"
6->"June"
7->"July"
8->"Aug"
9->"Sept"
10->"Oct"
11->"Nov"
12->"Dec"
else -> {
println("Not a month of the year")
}
}
println(months)
}
If the argument doesn’t satisfy any of the branch requirements, the else
branch is performed. The else branch is required as an expression, unless
the compiler can demonstrate that all possible scenarios are handled by
branch conditions. If we are unable to use the else branch, a compiler error
will be generated.
Error:(7, 16) Kotlin: “when” expression must be exhaustive, add neces-
sary “else” branch.
import java.util.Scanner;
fun main(args: Array<String>) {
var reader = Scanner(System.'in')
print("Enter the name of planet: ")
var names = reader.next()
when(names) {
"Mercury","Earth","Mars","Jupiter",
"Neptune","Saturn","Venus","Uranus" ->
println("Planet")
else -> println("Neither the planet nor the
star")
}
}
import java.util.Scanner;
fun main(args: Array<String>) {
var reader = Scanner(System.'in')
print("Enter month number of the year: ")
var numb = reader.nextInt()
when(numb){
in 1..3 -> println("It is the spring season")
in 4..6 -> println("It is the summer season")
in 7..8 ->println("It is the rainy season")
in 9..10 -> println("It is the autumn season")
in 11..12 -> println("It is the winter
season")
!in 1..12 ->println("Enter the valid month of
year")
}
}
Control Flow Statements ◾ 145
while(test expression) {
// the code to run
if(break condition) {
break
}
// the another code to run
}
A Kotlin program that computes the sum of integers from 1 to 10:
var c = 1
while(i <= Int.MAX_VALUE) {
sum += c
c++
if(c == 11) {
break
}
}
print("sum of integers from 1 to 11: $sum")
}
In the above program, we use a while loop and a break expression to com-
pute the sum of numbers from 1 to 10. Create a variable sum and set its ini-
tial value to 0. Iterate through the loop again, and this time set variable I to 1.
Iterator now proceeds from i = 1) and executes the sum statement.
When the iterator value i reaches 11, the break expression is executed, and
the loop is exited without testing the test expression i = Int.MAX VALUE).
The control then goes to the while block’s print() instruction, which prints
the total of integers = 55.
do {
//the code to run
if(break-condition) {
break
}
while(test-expression)
do{
println("The name of $c th planet: "+name[c])
if(name[c]=="Jupiter") {
break
148 ◾ Mastering Kotlin: A Beginner’s Guide
}
c++
}while(c<=name.size)
}
break
}
}
}
outer@ while(condition) {
// code…
inner@ while(condition) {
// code…
if(break-condition) {
break @outer
}
}
}
150 ◾ Mastering Kotlin: A Beginner’s Guide
outer@ do {
// code..
inner@ do {
// code..
if(break-condition) {
break@outer
}
} while(condition)
} while(condition)
var numb2 = 4
inner@ do {
if (numb1 == 2)
break@outer
println("numb1 = $numb1; numb2 = $numb2")
numb2--
} while (numb2 > 0)
numb1--
} while (numb1 > 0)
}
We print the same output as in the while loop here. When the (num1 == 2)
expression is true, the break@outer command is performed, which ends
the desired loop marked with outer@.
while(condition) {
//code…
if(condition for continue) {
continue
}
//code…
}
Control Flow Statements ◾ 153
Flowchart:
In the preceding program, we print the integers and skip all multiples of 3.
The phrase (num % 3 == 0) is used to determine if a number is divisible
by 3. If the number is a multiple of three, increase it without printing it to
standard output.
do{
// code…
if(condition for continue) {
continue
}
}
while(condition)
Flowchart:
Flowchart:
outer@ while(first-condition) {
// code…
inner@ while(second-condition) {
//code…
if(condition for continue) {
continue@outer
}
}
}
outer@ do {
// code…
inner@ do {
// code…
if(condition for continue) {
continue@outer
}
} while(first-condition)
} while(second-condition)
CONCLUSION
This chapter covered the control flow statement where we learned if-
else, while loop, do-while loop, and for loop. Moreover, we covered when
expression, labeled and unlabeled break, and labeled and unlabeled
continue.
Chapter 5
IN THIS CHAPTER
ARRAYS IN KOTLIN
The array data structure is one of the most fundamental data structures in
almost all computer languages. Array is a data-structure that allows us to
store several items of the same data type, such as integer or string, under
a single variable name.
Arrays are used in programming to arrange data so that a related group
of values can be readily sorted or searched.
DOI: 10.1201/9781003311904-5 161
162 ◾ Mastering Kotlin: A Beginner’s Guide
Creation of an Array
Arrays are not native data types in Kotlin, but rather a mutable collection
of related items represented by the Array class.
In Kotlin, an array may define in two ways.
Syntax:
val numb = arrayOf(1, 2, 3, 4) //type
declaration implicit
val numb = arrayOf<Int>(1, 2, 3) //type
declaration explicit
fun main()
{
// declarion of array using arrayOf()
val arrayname = arrayOf(11, 22, 33, 44, 55)
for (c in 0..arrayname.size-1)
{
print(" "+arrayname[c])
}
println()
// the declarion of an array using arrayOf<Int>
val arrayname2 = arrayOf<Int>(1, 2, 3, 4, 5)
Arrays and Strings, Functions, and Java Interoperability ◾ 163
for (c in 0..arrayname2.size-1)
{
print(" "+arrayname2[c])
}
}
Syntax:
val numb = Array(3, {c-> c*1})
In the above example, we pass the array’s size as 3 and a lambda function
that initializes element values from 0 to 9.
Program of creating array using constructor:
fun main()
{
val arrayname = Array(5, { c -> c * 1 })
for (c in 0..arrayname.size-1)
{
println(arrayname[c])
}
}
Aside from these, Kotlin provides various built-in factory methods for cre-
ating arrays of primitive data types like byteArray, intArray, shortArray,
and so on. Although they implement the same methods and attributes,
these classes do not extend the Array class.
The factory method for creating an integer array, for example:
• byteArrayOf()
• charArrayOf()
• shortArrayOf()
• longArrayOf()
• Using the get() and set() Functions: As you may be aware, an array
in Kotlin is essentially a class. As a result, we may access a class
object’s data using its member functions. The methods get() and set()
are referred to as member functions.
The get() function accepts a single parameter, the element’s index,
and returns the item’s value at that index.
First Syntax:
val x = numb.get(0)
The set() function accepts two parameters: the element’s index and
the value to insert.
Second Syntax:
num.set(1, 3)
numb[2] = 5;
The value of the third element in the numb array will change to 5.
Note that the index operator, or [], is an overloaded operator that
only stands for calls to the get() and set() member functions.
Here’s an example of Kotlin array manipulation in action, in
which we build an array, edit its values, and access a specific element:
fun main()
{ // declare an array using arrayOf()
val numb = arrayOf(1, 2, 3, 4, 5)
Array Traversal
An array’s key quality is that it can traverse programmatically, and each
element in the array may change separately. Kotlin provides a few useful
methods for traversing arrays.
The for-loop is the simplest and most often used idiom for traversing
an array.
First Syntax:
for(c in numb.indices){
println(numb[c])
}
// traversing an array
fun main()
{
val numb = arrayOf<Int>(1, 2, 3, 4, 5)
166 ◾ Mastering Kotlin: A Beginner’s Guide
numb.set(0, 10)
numb.set(1, 6)
for (c in numb.indices)
{
println(numb[c])
}
}
To get the same result, we may also utilize the range. A range in Kotlin is
an interval between two values (start and finish) that may create with the
(..) operator. The in keyword may then use to traverse the range.
Range syntax is as follows:
for (c in 0..10){
println(c)
}
// traversing an array
fun main()
{
val arraynames = arrayOf<Int>(1, 2, 3, 4, 5)
for (c in 0..arraynames.size-1)
{
println(arraynames[c])
}
}
Second Syntax:
arraynames.forEach({index->println(index)})
// traversing an array
fun main()
Arrays and Strings, Functions, and Java Interoperability ◾ 167
{
val arraynames = arrayOf<Int>(1, 2, 3, 4, 5)
arraynames.forEach({ index -> println(index) })
}
STRING IN KOTLIN
A string is an array of characters. Kotlin strings are comparable to Java
strings; however, they include several additional features. Kotlin strings
are likewise immutable, which implies that we cannot modify the compo-
nents or length of the string.
In Kotlin, the String class is defined as follows:
In Kotlin, we must use double quotes (" ") to declare a string; single quotes
are not permitted to define strings.
Syntax:
var variable_name = "Hello, Everyone"
or
• String elements
A character, digit, or other symbols in a string is referred to as an
element of a string. Using string[index], we can quickly get the ele-
ment of the string. Elements are stored in a string starting at index 0
and ending at (string.length – 1).
In Kotlin, string elements may access in three ways:
• Using index: This method returns the character at the specified
index.
168 ◾ Mastering Kotlin: A Beginner’s Guide
• String Template
String template expressions are evaluated pieces of code, and the
results are delivered as strings. Template expressions can found in
both escaped and raw string types. String templates begin with a dol-
lar sign $ and are followed by either a variable name or an arbitrary
expression enclosed in curly braces.
fun main(args: Array<String>) {
var num = 10
println("The value of n is $num")
// using string
val str = "Everyone"
println("$str is string which length is ${str.
length}")
}
The string has the following essential properties and functions:
• Length: It returns the length of string.
var st =" String"
println(st.length)
Arrays and Strings, Functions, and Java Interoperability ◾ 169
String Literals
In Kotlin, there are two kinds of string literals:
• Escaped string
• Raw string
Escaped String
An escape string is defined with double quotes ("....") and may contain
escape characters such as /n, /t, and so on.
Escaped string Kotlin program:
Escape Characters
Some of the escapees include:
String Equality
Kotlin includes comparing instances of a specific type in two separate
ways. This characteristic distinguishes Kotlin from other programming
languages.
There are two kinds of equality:
• Structural equality
• Referential equality
Arrays and Strings, Functions, and Java Interoperability ◾ 171
Structural Equality
The = = operator and its inverse, the != operator, assess structural equality.
The expression x==y is converted into a call to the type’s equals() method
by default.
Referential Equality
In Kotlin, referential equality is tested using the = = = operator and its
opposite, the != = operator. This equality returns true only if two instances
of the same type refer to the same memory location. When used on types
that are converted to primitives at runtime, the = = = check is converted to
= = check, and the != = check is converted to != check.
Program to demonstrate the structural and referential equality:
FUNCTIONS IN KOTLIN
Function is a piece of code that does a specific task. Functions are used in
programming to divide code into smaller modules, making the program
more manageable.
For instance, if we need to compute the sum of two numbers, we may
create a fun sum ().
We may call sum(c, d) many times as we like, and it will always return
the sum of two values. As a result, the function minimizes code repetition
and makes code more reusable.
There are two kinds of functions in Kotlin:
The following is a list of some standard library functions and their use:
To multiply two numbers with the same kind of arguments, use the
Kotlin method mul():
}
fun main(args: Array<String>) {
var result = mul(4,6)
println("Multiplication of 2 numbers is: $result")
}
}
fun main(args: Array<String>) {
val name = "Pariniti"
val rollno = 23
val grade = 'C'
students(names,grades,rollno)
students("Gautam",'C',25)
}
• Default arguments
• Named arguments
students(names_of_student,standard_of_students,roll_
no_of_students)
}
Arrays and Strings, Functions, and Java Interoperability ◾ 179
In the preceding program, we did not send the parameters in the order
stated in the function. As a result, it returns a compilation error.
Named arguments are parameters that are supplied using the name
while calling a function. We must use name of the formal argument to
which we are passing the actual argument value when calling the function.
Program for calling students() with the following arguments:
students(names=names_of_students,roll_no=roll_no_of_
students)
}
Explanation: In this case, we used the name to pass the actual arguments
to the formal arguments. We just gave the values for name and roll no;
therefore, it prints the default value of “Students standard.”
RECURSION IN KOTLIN
We will learn how to use the Kotlin recursive function. In Kotlin, we may
utilize recursion just like in other programming languages.
A recursive function calls itself, and the act of recurrence is known as
recursion.
When a function is called, one of two things is possible:
fun callMe(a:Int) {
println(a)
if (a > 0) callMe(a – 1)
}
fun main (args: Array <String>) {
var n = 5
callMe()
• In tail recursion, the function call is the last item done by the function,
and there is nothing left to run in the current function. As a result,
there is no need to save the current function call in stack memory,
and the compiler can reuse that stack space for the next recursive call.
• StackOverflowError does not occur during program execution in tail
recursion.
Lambda Expressions
As we all know, the syntax of Kotlin lambdas is quite similar to that of
Java lambdas. An anonymous function does not have a name. We may call
lambda expressions anonymous functions.
First Example:
fun main(args: Array<String>) {
val company = { println("PeeksforPeeks")}
// invoking the function method1
company()
Arrays and Strings, Functions, and Java Interoperability ◾ 185
Syntax:
val lambda_names : Data_type = { argument_List ->
code_body }
Second Example:
val sum = {x: Int, y: Int -> x + y}
Except for the code body, the lambda expression in Kotlin has optional
parts. The lambda expression is shown below after the optional component
has been removed.
It’s worth noting that we don’t always need a variable because it can be
supplied directly as an argument to a method.
Program:
In this case, the Kotlin compiler evaluates it as a function that takes two
Int parameters and returns an Int value.
(Int,Int) -> Int
Anonymous Function
An anonymous function is quite similar to a regular function except for
the omission of the function’s name from the declaration. The anonymous
function’s body can be either an expression or a block.
This implies that a return within a lambda expression returns from the
enclosing function, but a return within an anonymous function returns
from the anonymous function itself.
Program to call the anonymous function:
Example:
fun higherfunc( str1 : String, mycall :(String)->
Unit) {
// invokes print() by passing the string str1
mycall(str1)
}
print("Huboftutors: ")
higherfunc("A Computer Science portal for
Hub",::print)
}
mycall.invoke(str1)
mycall(new-Function() {
@Override
public void invoke() {
//the println statement is called here.
}
});
The println lambda expression is copied in the main function in the form
of System.out.println with the assistance of the inline keyword, and no
additional calls are necessary.
Crossline Keyword
Return in lambda in the preceding program exits both the inline function
and enclosing function. To stop the lambda expression from returning,
we can use the crossline. If it encounters a return statement in the lambda
expression, it will generate a compiler error.
Example:
fun main(args: Array<String>){
println("The Main function starts")
inlinedfunc({ println("Lambda-expression 1")
return }, // It gives the compiler
error
{ println("Lambda-expression 2")} )
Noinline
If we want part of the lambdas passed to an inline function to inline, we
may use the noinline modifier on some of the function arguments.
Properties of Inline
Inlined functions copy the code to the calling location, while inline key-
words copy the inline property accessor methods to the calling location.
The inline modifier can use to property accessors that do not have a back-
ing field.
class maths {
// the user defined infix member function
infix fun square(x : Int): Int{
val num = x * x
return num
}
}
fun main(args: Array<String>) {
val y = maths()
// the call using infix notation
val result = y square 3
print("The square of a number is: "+result)
}
Then, we created an object for the class maths() and invoked the method
using infix notation.
y square 3
class checks{
// the user defined infix member function
infix fun dataType(a: Any):Any{
var x = when(a){
is String -> "String"
is Int -> "Integer"
is Double -> "Double"
else -> "invalid"
}
return x
}
}
fun main(args: Array<String>){
var chk = checks()
// call using infix notation
var results = chk dataType 3.3
println(results)
}
when the data type of the passing argument is checked, and the required
result is returned.
It returns double to the standard output in this case.
On the other hand, Infix function calls take priority over the Boolean
operators && and ||, is- and in-checks, and several other operators.
The following expressions are also equivalent:
Higher-Order Function
Higher-Order functions in Kotlin are functions that can receive a function as
an argument or return a function. We shall pass anonymous functions or lamb-
das instead of passing integer, string, or array as function parameters. Lambdas
are frequently passed as parameters in Kotlin functions for simplicity.
The lambda expression is passed as an argument to the higher-order
function: A lambda expression can be passed as a parameter to higher-
order function.
There are two kinds of lambda expressions that may be passed:
// lambda expression
var lambda = {println("Huboftutors: A Computer Science
portal for Hub") }
//the higher-order function
fun higherfunc( lmbd: () -> Unit ) { // accepting
lambda as parameter
Arrays and Strings, Functions, and Java Interoperability ◾ 199
higherfunc(lambda)
// lambda expression
var lambda = {x: Int, y: Int -> x + y }
// the higher order function
fun higherfunc( lmbd: (Int, Int) -> Int) { //
accepting the lambda as parameter
higherfunc(lambda)
It is given two parameters. One is the string type, and the other is the
function.
The higher function is invoked from the main function by supplying the
string and function as arguments.
Properties of Kotlin
In Java, a property is defined as a private field with the same name as the
property and a getter and setter method, with get and set prefixed to the
property name. This private field may be found in the java class created
from the Kotlin file.
In Java, for example, the property var age: Int is compiled to the follow-
ing code:
These attributes may be accessed via the class’s object, much like in Java.
If the property name begins with is, the get keyword is skipped from the
getter function’s name.
Package-Level Functions
All Kotlin functions declared within a package are compiled into static
Java methods within a class whose classname is a mixture of the package
name and the filename.
For example, suppose there is a package named kotlinPrograms and a
Kotlin file called firstex.kt that has the following code.
// Java
new kotlinPrograms.firstex.myClass()
kotlinPrograms.Firstexkt.add(3, 5);
Using the @JvmName annotation, we may alter the name of the pro-
duced Java class:
// Kotlin file
@file : Jvmname("Samples")
package kotlinPrograms
class myclass {
fun add(val x:Int, val y:Int): Int {
return x+y;
}
}
// Java
new kotlinPrograms.firstex.myClass()
kotlinPrograms.Samples.add(3, 5);
Having numerous files with the same name, on the other hand, is a logical
mistake. To overcome this limitation, Kotlin gives its compiler the ability
to generate a façade class with a specific name containing all declarations
from all files with the same name. To develop such a facade class, provide
the annotation @JvmMultiFileClass in all files.
Example:
// Kotlin code
@file:JvmName("Samples")
@file:JvmMultiFileClass
package samples.example
fun print(){.......}
// Kotlin code
@file:JvmName("Samples")
@file:JvmMultiFileClass
Arrays and Strings, Functions, and Java Interoperability ◾ 205
package samples.example
fun printString(){.......}
Static Fields
In Java, static fields are properties specified within a named object or a
companion object in Kotlin. To access these fields in Java, they must be
annotated with the @JvmField annotation, defined with the lateinit modi-
fier, or annotated with the const modifier.
Example:
// filename Example.kt
// Property in companion object
class xyz{
companion object{
@JvmField
val a = 4;
}
}
// A constant property
const val b = 4;
Static Methods
Methods declared at the package level are always created in the Java code
as static methods. Methods specified in named objects and companion
objects annotated with @Jvm are also included. Static annotations are cre-
ated in the same way as static methods are. This annotation indicates that
the following method is a class function.
Example:
// filename Example.kt
class xyz {
companion object {
206 ◾ Mastering Kotlin: A Beginner’s Guide
//Java usage
xyz.add(); // works fine
xyz.sub(); // error: not a static method
xyz.Companion.add(); // instance method remains
Z.Companion.sub(); // the only way it works
Instance Fields
Kotlin has a feature that allows us to utilize the property as an instance
field in Java. Annotate the property with the @JvmField annotation to do
this. The visibility of these instance fields is the same as that of the Kotlin
property. The property, however, must have a backing field and cannot be
defined with the private, open, const, or override modifiers.
Example:
// Kotlin code
class XYZ(z: Int){
@JvmField val id = z
}
Checked Exceptions
In Kotlin, all exceptions are unchecked. As a result, the Java signatures of
Kotlin functions never declare nor handle the exceptions that are thrown.
To address this issue, the Kotlin function must be annotated with the
@Throws annotation, which specifies the exception that will be thrown.
The Java signature will also declare the function that will throw in this
instance.
Arrays and Strings, Functions, and Java Interoperability ◾ 207
Example:
// samples Kotlin function
// filename example.kt
package Samples
fun print(){
throws IOException()
}
So, in order to address the error, we declare the @Throws annotation at the
beginning.
// Kotlin file
fun main(){
val ob = example()
ob.values = 5 // This will call the setter function
println(ob.values) // This will call the getter
function
}
Methods
Calling Java methods from within Kotlin is a simple idea. The arguments
to be given are the same in both Java and Kotlin, as is the function’s return
type. The void return type is the lone exception to this rule. In Kotlin,
functions with a void return type in Java return a Unit type. Because Unit
is a type in Kotlin, this value may store.
Java file declared as example.java:
// Java code
public class program {
public int add(int c, int d){
return c+d;
}
}
// Kotlin file
fun main(args: Array<String>) {
Arrays and Strings, Functions, and Java Interoperability ◾ 209
val ob = myjava()
val ans = ob.add(14, 4)
println("Sum of two numbers is "+ans)
}
Note: Some Kotlin keywords may be used as valid identifiers in Java. For
instance, any, sealed, object, and so on. If this is the case, use identifiers in
Kotlin, enclosing them in a backtick character (’).
For instance, if a Java class ABC has a method named any, the method
may be invoked in Kotlin as:
Static Members
In Kotlin, the static class members become the members of a compan-
ion object. These companion objects, however, cannot be utilized directly
in expressions. To gain access to its members, utilize the member’s fully
qualified name as defined in Java.
Java file declared as example.java:
// Java Code
package mypackage;
public class example {
public static void display() {
System.out.println("Call-successful")
}
}
Java Arrays
In contrast to Java arrays, which may be assigned to an array of type
Object, Kotlin offers an invariant form of arrays, which means that arrays
of a certain type cannot give to an array of type Any.
Furthermore, arrays of subclass types cannot be assigned to arrays of
superclass types in Kotlin.
Because Kotlin does not provide arrays for primitive types, it offers
numerous specialized classes in Java to represent an array of primi-
tive kinds. These classes are unrelated to the Array class, and they are
compiled into simple java arrays for optimum speed. This conversion
to bytecode adds no additional cost, regardless of how the arrays are
utilized.
Java file declared as example.java:
// Java Code
public class example {
int results = 0;
public int compute(int[] array)
{
for(int x: array){
results = result + x;
}
return results;
}
}
// Kotlin-code
fun main(args: Array<String>) {
// Kotlin-code
val ob = example()
val array = intArrayOf(11, 22, 33, 44, 55, 66)
var sum1 = ob.compute(array)
println("The sum of an array is "+sum1)
}
Java Varargs
In functions, Java supports the concept of variable-length arguments,
which means that when the number of arguments to a function is unknown
but their type is known, we define a varargs parameter. Kotlin does not
Arrays and Strings, Functions, and Java Interoperability ◾ 211
// Java code
public class example {
public void myfunc(String str1,int... numbers) {
System.out.println("Passed string is " +
str1);
for (int nu : numbers) {
System.out.print(" "+nu);
}
}
}
// Kotlin code
fun main(args: Array<String>) {
val ob = example()
val array = intArrayOf(12, 21, 13)
ob.myfunc("Peeks", *array)
}
Some of the java.lang package’s built-in classes are also mapped to Kotlin
classes:
In Kotlin, the boxed types of Java’s primitive data types are mapped to
nullable types:
CONCLUSION
In this chapter, we covered array and string in Kotlin, functions where we
also covered inline, infix function, tail recursion, and lambda expressions.
Moreover, we covered Java interoperability.
Chapter 6
Collections in Kotlin
IN THIS CHAPTER
➢➢ Collection
➢➢ ArrayList, listOf, setOf
➢➢ HashSetOf
➢➢ Map, HashMap
➢➢ Annotations, Reflection, Overloading
➢➢ Tuple in Kotlin
COLLECTIONS IN KOTLIN
Kotlin, like Java Collections, introduces the idea of collections. A collec-
tion often comprises a number of objects of the same type, referred to as
elements or items in the collection. The Kotlin Standard Library provides
a complete set of utilities for managing collections.
Types of Collections
Collections in Kotlin are classified into two types:
1. Immutable Collection
2. Mutable Collection
DOI: 10.1201/9781003311904-6 213
214 ◾ Mastering Kotlin: A Beginner’s Guide
Immutable Collection
It signifies that it only provides read-only functionality and that its ele-
ments cannot edit. Immutable collections and their associated techniques
are as follows:
for(item in immutableSets){
println(item)
}
}
Map Each key in a Map is unique and holds just one value; it is a set of
key-value pairs. Each key corresponds to a single value. Values can dupli-
cate, but keys must be distinct. Maps are used to store logical link between
the two things such as a student’s ID and name. Its size is fixed since it
is immutable, and its methods provide read-only access. The following
Kotlin application demonstrates the immutable Map:
Mutable Collection
It has both read and write capabilities. Mutable collections and their asso-
ciated techniques are as follows:
List Because mutable lists may be read and written to, defined elements
in the list can be deleted or added. The following Kotlin program demon-
strates the mutable list:
mutableLists[0] = "Praniti"
// add one more element in list
mutableLists.add("Abhi")
for(item in mutableLists){
println(item)
}
}
Set The mutable Set allows for both read and write operations. We may
simply add or delete elements from the collections, and the order of the
components is preserved. To show the mutable set, write the following
Kotlin program:
ARRAYLIST IN KOTLIN
In Kotlin, the ArrayList class is used to generate a dynamic array. The term
“dynamic array” refers to the ability to grow or reduce the size of an array
based on the needs. It also has read and write capabilities. ArrayList is
Collections in Kotlin ◾ 217
Example:
fun main(args: Array<String>) {
// creation of an empty arraylist using
constructor
var arraylists = ArrayList<String>()
//adding String elements in the list
arraylists.add("Peeks")
arraylists.add("Peeks")
// iterating the list
println("Array list ---->")
for(i in arraylists)
println(c)
arraylists.add( 1, "of")
println("Arraylists after insertion:")
for(i in arraylists)
println(c)
}
var arraylist=ArrayList<String>()
//adding String elements in the list
arraylists.add("Peeks")
arraylists.add("of")
arraylists.add("Peeks")
// creating the new arraylist1
var arraylists1=ArrayList<String>()
//adding all elements from arraylists to arraylists1
println("Elements in arraylist1:")
arraylist1.addAll(arraylists)
for(c in arraylists1)
println(c)
}
get(index: Int): E: It is used to return the element in the list at the provided
index.
arraylists.add("Peeks")
arraylists.add("of")
arraylists.add("Peeks:")
arraylists.add("Portal")
// iterating through elements
for(i in arraylists)
print("$c")
println()
// set element at index 3 with new string
arraylist.set(3,"A computer Science portal for
students")
// iterating through the elements
for(i in arraylist)
print("$c")
}
indexOf(element: E): Int: It is used to return the index of the first occur-
rence of the specified element in the list, or –1 if the specified element does
not appear in the list.
var arraylists=ArrayList<String>()
// adding the elements
arraylists.add("Peeks")
arraylists.add("for")
arraylists.add("Peeks")
arraylists.remove("of")
// iterating through elements
for(c in arraylists)
print("$c ")
}
LISTOF() IN KOTLIN
A list is a collection of elements sorted in a specific way. Kotlin provides
two types of lists: immutable (non-modifiable) and mutable (modifiable)
(can be modified).
Read-only lists are produced using listOf(), and their items cannot edit,
but mutable lists are generated with the mutableListOf() function and
their elements may be altered or modified.
Collections in Kotlin ◾ 221
Explanation:
for (name in names1) {
print("$name, ")
}
The for loop iterates across the list. The variable “name” points to the next
member in the list in each cycle.
This approach takes advantage of the list’s size. The till keyword creates a
range of list indexes.
We loop over the list with index and value available in each iteration using
the forEachIndexed() method.
Explanation:
val asc1 = list.sorted()
The list is sorted in the ascending order via the sorted() function.
Explanation:
val res = lists.contains(0)
Checks if the lists include 0 and return true or false (her true), saved in
res1.
SetOf () in Kotlin
The Kotlin Set interface is a general unordered collection of items that
includes duplicates. Kotlin recognizes two kinds of sets: mutable and
immutable.
Syntax:
fun <D> setOf( vararg elements: D): Set<D>
Set Indexing
The index of the specified element can be obtained using the index func-
tions indexOf() and lastIndexOf(). We may also use the elementAt()
method to find elements at a given index.
Index-using Kotlin program:
Set the first() and last() element: The first() and last() methods may be
used to obtain the first and last element of a set.
Example:
fun main(args: Array<String>){
val captain = setOf(1,2,3,4,"Kanika",
"Smridhi",
"Ruhi","Mayank","Ridhi","Daman")
Set Basics
We will go over fundamental methods such as count(), max(), min(),
sum(), and average().
Basic functions are used in a Kotlin program:
Syntax:
fun <D> mutableSetOf( vararg elements: D): MutableSet
<D>
Description:
Example:
fun main(args: Array<String>)
{
//declaring mutable set of integers
val seta1 = mutableSetOf( 11, 22, 33,
44, 33);
println(seta1);
//adding the elements 66 & 77
seta1.add(66);
seta1.add(77);
println(seta1);
//removing the 33 from the set
seta1.remove(33);
println(seta1);
//another way to add the elements is by using
listOf() function
seta1 += listOf(88,99)
println(seta1)
}
Set Indexing
The index of the specified element may be obtained using the index meth-
ods indexOf() and lastIndexOf(). We may also use the elementAt() method
to find elements at a given index.
Index-using Kotlin program:
Example:
fun main(args: Array<String>){
val captain = mutableSetOf(11,22,33,44,"Kanika
","Smridhi",
"Ruhi","Mayank","Daman","Ridhi")
println("first element of the set is:
"+captain.first())
println("last element of the set is:
"+captain.last())
}
Traversal in a MutableSet
In a MutableSet, we can perform for loop using an iterator to traverse all
the elements in the set.
HASHSETOF() IN KOTLIN
Kotlin HashSet is a generic unordered collection of elements that contains
no duplicates. It is responsible for implementing the set interface. hashSe-
tOf() is a function that returns a mutable HashSet that may be read as well
as written. The HashSet class uses hashing to store all of the elements.
Syntax:
fun <D> hashSetOf(vararg elements: T): HashSet <D>
Example:
fun main(args: Array<String>)
{
//declaring hash set of integers
val seta1 = hashSetOf(11,22,33,33);
//printing the first set
println(seta1)
//declaring hash set of strings
val setb1 = hashSetOf("Peeks","of","peeks");
println(setb1);
}
• The add() and addAll() methods can use to add elements to a HashSet.
• Using the remove() method, we may delete an element.
HashSet Traversal
We can traverse HashSet using an iterator in a loop.
Indexing in a HashSet
Using the index methods indexOf() and lastIndexOf(), we may get the
index of the specified element. We may also use the elementAt() method
to find elements at a given index.
Index-using Kotlin program:
Checking the equality of empty hash sets and employing the isEmpty()
functions:
MAPOF() in Kotlin
A Kotlin Map is a collection of pairings of objects. The data in a Map
is stored in the form of pairs, each of which consists of a key and a
value. Map keys are one-of-a-kind, and the Map only stores one value
for each key.
Collections in Kotlin ◾ 235
Syntax:
fun <X, Y> mapOf(vararg pairs: Pair<X, Y>): Map<X, Y>
• The pair’s first value is the key, and the second is the value of the
associated key.
• If many pairs have the same key, the Map will return the last pair’s
value.
• The Map entries are traversed in the order indicated.
Map Size
There are two ways to determine the size of a Map. By using the Map’s size
property and the count() method.
236 ◾ Mastering Kotlin: A Beginner’s Guide
fun main() {
val ranks1 = mapOf(1 to "London",2 to "Africa",3
to "Germany",4 to "Canada")
//method 1
println("size of the map is: "+ranks1.size)
//method 2
println("size of the map is: "+ranks1.count())
}
Empty Map
Using mapOf, we may generate an empty serializable map ().
MapOf() Example:
fun main() {
val ranks1 = mapOf(1 to "London",2 to "Africa",3
to "Germany",4 to "Canada")
//method 1
println("The Team having rank #1 is: "+ranks1[1])
//method 2
println("The Team having rank #3 is: "+ranks1.
getValue(3))
//method 3
println("The Team having rank #4 is: "+ranks1.
getOrDefault(4, 0))
// method 4
val teams = ranks1.getOrElse(2, { 0 })
println(teams)
}
Collections in Kotlin ◾ 237
fun main() {
val colorsTopToBottom = mapOf("green" to 1,
"yellow" to 2, "pink" to 3,
"white" to 4, "brown" to 5, "blue" to 6,
"purple" to 7)
var colors = "yellow"
if (colorsTopToBottom.containsKey(colors)) {
println("Yes, it contains the color
$colors")
} else {
println("No, it does not contain the color
$colors")
}
val values = 8
if (colorsTopToBottom.containsValue(values)) {
println("Yes, it contains the value
$values")
} else {
println("No, it does not contain the value
$values")
}
}
Example:
fun main(args: Array<String>)
{
//lets make the two values with same key
val map1 = mapOf(1 to "peeks1",2 to "of", 1
to "peeks2")
// return map entries
println("Entries of map: " + map1.entries)
}
238 ◾ Mastering Kotlin: A Beginner’s Guide
Explanation: In this case, key value 1 has been set with two values: peeks1
and peeks2, but because mapOf() may only have one value for one key
item, the Map only stores the last value, and peeks1 is removed.
HASHMAP IN KOTLIN
Kotlin HashMap is a collection that includes object pairs. MutableMap imple-
mentation in Kotlin using Hash Tables. It keeps data in the form of a key and
value pair. Map keys are one-of-a-kind, and the Map only stores one value for
each key. It’s represented as HashMapkey, value> or HashMapK, V>.
HashMap’s hash table-based implementation makes no guarantees
regarding the order of given data of key, value, and collection elements.
Kotlin HashMap class constructors are available: Kotlin HashMap
has four constructors, each with a public access modifier:
hashMap1.put("IronMan", 3200)
hashMap1.put("Thor", 100)
hashMap1.put("SpiderMan", 1300)
hashMap1.put("NickFury", 1100)
hashMap1.put("HawkEye", 1400)
//printing the non-Empty hashMap1
printHashMap(hashMap1)
//using overloaded print function of
//Kotlin language to get same results
println("hashMap1 : " + hashMap1 + "\n")
for(key in hashMap1.keys) {
println("Element at key $key :
${hashMap1[key]}")
}
//return the size of hashMap1
println("\n" + "hashMap1.size : " + hashMap1.size )
for(key in hashMap1.keys) {
println("Element at key $key :
${hashMap1[key]}")
}
}
hashMap1.put("Iron-Man", 3200)
hashMap1.put("Thor", 120)
hashMap1.put("Spider-Man", 1300)
hashMap1.put("Cap", 1400)
for(key in hashMap1.keys) {
println("Element at the key $key :
${hashMap1[key]}")
}
//the hashMap1's elements can be accessed like
this
println("\nhashMap1[\"Iron-Man\"] : "
+ hashMap1["Iron-Man"])
hashMap1["Thor"] = 2000
println("hashMap1.get(\"Thor\") : "
+ hashMap1.get("Thor") + "\n")
//replacing some value
hashMap1.replace("Cap", 989);
hashMap1.put("Thor", 2200);
println("hashMap1.replace(\"Cap\", 989)" +
" hashMap1.replace(\"Thor\", 2200)) :")
for(key in hashMap1.keys) {
println("Element at key $key : ${hashMap1
[key]}")
}
}
ANNOTATIONS IN KOTLIN
Annotations are a Kotlin feature that allows the programmer to embed
additional information in the source file. This information, however, does
not affect the program’s activities. A variety of tools utilizes this data dur-
ing both development and deployment.
The following arguments are typically included in annotations and
must be compile-time constants:
Using Annotation
We may use annotation by placing its name in front of a code element and
prefixing it with the @ symbol. For example, if we want to use the annota-
tion Positive, we should write the following. If we want to use the annota-
tion Pos, we should write the following:
@Allowedlanguage("Kotlin")
@Throws(IOException::class)
Collections in Kotlin ◾ 243
Declaring Annotation
An annotation is declared by prefixing the class keyword with the anno-
tation keyword. Annotation declarations, by definition, cannot include
code. When we declare our annotations, we must describe which code
components they may apply to and where they should be kept.
The most basic annotation has no parameters:
Annotate a Constructor
We may also annotate the constructor of a class. It is possible to accom-
plish this by utilizing the constructor keyword for constructor declaration
and inserting the annotation before it.
Annotate a Property
We may annotate the class’s properties by adding annotations to the prop-
erties. We assume that a Lang instance is valid if the name value is either
Kotlin or Java in the following example.
class Lang (
@Allowedlanguages(["Java","Kotlin"]) val name:
String)
}
@Target
This annotation indicates where the annotated annotation can be used,
such as classes, functions, constructors, type parameters, and so on. The
244 ◾ Mastering Kotlin: A Beginner’s Guide
@Target(AnnotationTarget.CONSTRUCTOR,
AnnotationTarget.LOCAL_VARIABLE)
annotation class AnnotationDemo2
class XYZ @AnnotationDemo2 constructor(val count:Int){
fun display(){
println("Constructor-annotated")
println("Count is $count")
}
}
fun main(){
val obj = XYZ(5)
obj.display()
@AnnotationDemo2 val message: String
message = "Hellooo"
println("Local-parameter-annotated")
println(message)
}
@Retention
This annotation indicates the availability of the annotated annotation, i.e.,
whether it remains in the source file or is available at runtime, and so on.
Its mandatory argument must be an instance of the AnnotationRetention
enumeration with the following elements:
• SOURCE
• BINARY
• RUNTIME
@Repeatable
This annotation allows an element to have applied the same annotation
numerous times. This annotation can only use with the Retention Policy
set to SOURCE in the present version of Kotlin 1.3.
Example:
@Repeatable
@Retention(AnnotationRetention.SOURCE)
annotation class AnnotationDemo4 (val value: Int)
@AnnotationDemo4(4)
@AnnotationDemo4(5)
fun main(){
println("The Repeatable Annotation applied on
main")
}
REFLECTION IN KOTLIN
Reflection is a set of the language and library capabilities that enable run-
time introspection of a particular program. Kotlin reflection is used at
runtime to access a class and its members, such as properties, functions,
constructors, etc.
Along with the Java reflection API, Kotlin has its own set of reflection
API, which is written in a simple, functional manner. The standard Java
Reflection constructs are likewise accessible in Kotlin and are fully com-
patible with its code.
Kotlin reflections are accessible in the following languages:
kotlin.reflect package
Reflection of Kotlin.
246 ◾ Mastering Kotlin: A Beginner’s Guide
Class References
Use the class reference operator to acquire a statically known class refer-
ence at runtime. In addition, a reference to a class can be derived from its
instances; such references are known as bounded class references. In the
case of inheritance, you may gain a reference to the specific type to which
the object adheres by using instances.
As an example of class references, consider the following:
Function References
We may retrieve a functional reference for each named function defined
in Kotlin. This is accomplished by using the :: operator before the function
name. These functional references can subsequently be passed to other func-
tions as arguments. In the case of overloaded functions, we may either explic-
itly provide the function type or be determined automatically from the text.
As an example of functional references, consider the following:
Property References
We can get property references in the same way we get function refer-
ences by using the :: operator. If the property is part of a class, the class-
name must also be given using the :: operator. These property references
enable us to treat a property as an object, retrieving its values using the get
method and editing it using the set function.
As an example of a property reference, consider the following:
Constructor References
A class’s constructor references can access the same way as method and
property references. These references can use to point to a function that
returns an object of the same type. These applications, however, are
uncommon.
As an example of constructor references, consider the following:
Unary Operators
The following table shows the different functions that can define for unary
operators. These functions make changes to the caller instance.
In this case, y represents the type for which the operator is defined. The
overloaded functionality is defined inside the functions themselves.
The following Kotlin program demonstrates unary operator
overloading:
str1 = str1.reversed()
}
}
// the main function
fun main(args : Array<String>) {
val obj1 = OverloadUnary ("HELLOOO")
println("Initial string is ${obj1.str}")y
//calling overloaded function unaryMinus()
-obj1
println("String after applying unary operator
${obj1.str1}")
}
return str1
}
}
// the main function
fun main(args: Array<String>) {
var obj1 = OverloadIncDec("Helloo")
println(obj1++)
println(obj1--)
println(++obj1)
println(--obj1)
}
Binary Operators
The following table lists the binary operators and their equivalent
functions. All of these functions have an effect on the calling instance.
Other Operators
Because Kotlin provides a diverse set of operators, specifying each for a
type is not a good programming practice. The following table lists some of
the additional useful operators in Kotlin that may be overloaded.
Example:
val (emps_id,salary) = employees
println(emps_id+" "+salary)
252 ◾ Mastering Kotlin: A Beginner’s Guide
fun main(){
val obj1 = sendData()
// Using instance to access the properties
println("Name is ${obj1.name}")
println("Age is ${obj1.age}")
EQUALITY EVALUATION
Kotlin includes comparing instances of a specific type in two separate
ways. This characteristic distinguishes Kotlin from other programming
languages.
There are two sorts of equality:
• Structural Equality
• Referential Equality
Structural Equality
Structural equality is tested using the = = operator and its opposite, the ! =
operator. By default, the phrase x= =y is converted into a call to the type’s
equals() method.
x?.equals(y)? : (y = = = null)
254 ◾ Mastering Kotlin: A Beginner’s Guide
Referential Equality
In Kotlin, referential equality is tested using the === operator and its
opposite, the !== operator. This equality returns true only if two instances
of the same type refer to the same memory address. When used on types
that are transformed to primitives at runtime, the === check is converted
to == check, and the !== check is converted to != check.
Program using Kotlin to illustrate structural and referential
equality:
class Squares(val side: Int) {
override fun equals(other: Any?): Boolean {
if(other is Squares){
return other.side == side
}
return false
}
}
//the main function
fun main(args :Array<String>) {
val squares1 = Square(4)
val squares2 = Square(7)
// structural equality
if(squares1 == squares2) {
println("The Two squares are structurally
equal")
}
// the referential equality
if(squares1 !== squares2) {
println("The Two squares are not referentially
equal")
}
}
Collections in Kotlin ◾ 255
KOTLIN COMPARATOR
When a new type is required in a programming context, the problem of
arranging the instances of that type becomes a crucial one. We implement
the comparable interface to compare two instances of a type. However,
since they must be compared automatically in ordering instances, and
because the order might vary depending on numerous criteria, Kotlin
offers a basic comparator interface. This interface compares and organizes
two items of the same type.
Function
compare: This function compares two instances of the same type and
returns zero if they are equal, a negative integer if the second instance is
larger, and a positive number otherwise.
Functions of Extension
reversed: This function accepts a comparator as an input and returns the
comparator with the same ordering as the passed comparator.
then: This function combines two comparator, and the second one is uti-
lized only when the values in the first comparator are equal.
fun main(){
val lists = ArrayList<Name>()
lists.add(Names("Stev","Wau"))
lists.add(Names("Stev","Smiti"))
lists.add(Names("Virati","Sohli"))
lists.add(Names("Kani","Will"))
lists.add(Names("Joti","Ruhan"))
fun main() {
val comparators = compareBy< Human > { it.height }
val list = listOf< Human >(
Human (6, 14),
Human(2, 15),
Human(5, 55),
258 ◾ Mastering Kotlin: A Beginner’s Guide
Human(4, 35),
Human(6, 85),
Human(5, 55)
)
fun main(){
val lists = listOf<Pairs<String,Int>>(
Pairs("D",3),
Pairs("C",1),
Pairs("E",345),
Pairs("P",20),
Pairs("S",0),
Collections in Kotlin ◾ 259
Pairs("B",0)
)
CONCLUSION
In this chapter, we covered collections where we learned what collection is,
including ArrayList, listOf, and setOf, and we also covered mutableSetOf,
HashSet, and Map in Kotlin. Moreover, we covered annotations, reflec-
tion, operator overloading, and destructing declaration. Also, we learned
about the equality equation and comparator.
Chapter 7
Android Development
with Kotlin
IN THIS CHAPTER
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hellooo World!"
app:layout_constraintBottom_toBottomOf=
"parent"
app:layout_constraintLeft_toLeftOf=
"parent"
app:layout_constraintRight_toRightOf=
"parent"
app:layout_constraintTop_toTopOf=
"parent" />
</android.support.constraint.ConstraintLayout>
• MainActivities.kt
In the example.app.javatpoint.helloworld package, create a
MainActivities.kt file, and add the following code.
package example.app.javatpoint.hellooworld
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
XML:
android:text="Fade Out"
android:textAllCaps="false" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:weightSum="1">
<Button
android:id="@+id/zoom_in"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="3"
android:text="Zoom In"
android:textAllCaps="false" />
<Button
android:id="@+id/zoom_out"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="2"
android:text="Zoom Out"
android:textAllCaps="false" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation=" vertical "
android:weightSum="3">
<Button
android:id="@+id/slide_down"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="2"
android:text="Slide Down"
android:textAllCaps="false" />
<Button
android:id="@+id/slide_up"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="2"
android:text="Slide Up"
android:textAllCaps="false" />
</LinearLayout>
Android Development with Kotlin ◾ 271
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:weightSum="1">
<Button
android:id="@+id/bounce"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="3"
android:text="Bounce"
android:textAllCaps="false" />
<Button
android:id="@+id/rotate"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="3"
android:text="Rotate"
android:textAllCaps="false" />
</LinearLayout>
</LinearLayout>
</RelativeLayout>
We will develop XML files for animations when we have modified the layout.
So, initially, we’ll make a folder called anim.
In this folder, we place the XML files that will utilize to generate the
animations. To accomplish this, go to app/res, right-click, and then pick
Android Resource Directory, and name it anim.
bounce.xml
XML: The text in this animation bounces like a ball.
<?xml version="1.0" encoding="utf-8"?>
<set
xmlns:android="http://schemas.android.com/apk/res/
android"
android:interpolator="@android:anim/
linear_interpolator"
android:fillAfter="true">
<translate
android:fromYDelta="90%"
android:toYDelta="-25%"
android:duration="320" />
<translate
272 ◾ Mastering Kotlin: A Beginner’s Guide
android:startOffset="550"
android:fromYDelta="-30%"
android:toYDelta="20%"
android:duration="140" />
<translate
android:startOffset="1100"
android:fromYDelta="15%"
android:toYDelta="0"
android:duration="120" />
</set>
fade in.xml
The text will appear from the background in the Fade In motion.
XML:
fade_out.xml
The color of text gets faded out for a set period of time in the Fade Out
animation.
XML:
rotate.xml
The text is rotated for a certain period of time in rotate animation.
XML:
slide_down.xml
The text in this animation will come from top to bottom.
XML:
slide_up.xml
The text in this animation will go from bottom to the top.
XML:
<set xmlns:android="http://schemas.android.com/apk/
res/android">
<translate
android:duration="1200"
android:fromYDelta="0"
android:toYDelta="-90%" />
</set>
274 ◾ Mastering Kotlin: A Beginner’s Guide
zoom_in.xml
The text in this animation will seem larger for a certain amount of time.
XML:
zoom_out.xml
The text in this animation will seem smaller for a certain length of time.
XML:
package peeksforpeeks.animationsinkotlin
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.os.Handler
import android.view.View
import android.view.animation.AnimationUtils
import kotlinx.android.synthetic.main.activity_main.*
textView.startAnimation(animationSlideDown)
}
slide_up.setOnClickListener {
val animationSlideUp = AnimationUtils.
loadAnimation(this, C.anim.slide_out)
textView.startAnimation(animationSlideUp)
}
bounce.setOnClickListener {
val animationBounce = AnimationUtils.
loadAnimation(this, C.anim.bounce)
textView.startAnimation(animationBounce)
}
rotate.setOnClickListener {
val animationRotate = AnimationUtils.
loadAnimation(this, C.anim.rotate)
textView.startAnimation(animationRotate)
}
}
}
AndroidManifest.xml File
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/
apk/res/android"
package="peeksforpeeks.animationsinkotlin">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.
action.MAIN" />
<category android:name="android.
intent.category.LAUNCHER" />
</intent-filter>
Android Development with Kotlin ◾ 277
</activity>
</application>
</manifest>
The first step is to open Android Studio and create a new project.
Follow these steps to accomplish this:
• Click File, then New, then New Project, then name it whatever we like.
• Then, choose Kotlin language support and press the next button.
• Choose the minimum SDKs we need.
• Choose Empty activity, and then click Finish.
• Following that, we must create our layout. We’ll need to use the XML
file for this. Navigate to app > res > layout and copy the following code:
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity" android:or
ientation="vertical">
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="PeeksofPeeks"
android:layout_centerInParent="true"
android:textSize="33sp"
android:textStyle="bold" />
<Button
android:id="@+id/fade_in"
android:layout_width="90dp"
android:layout_height="wrap_content"
android:text="Fade In"
android:layout_marginTop="150dp"
android:layout_marginLeft="90dp" />
<Button
android:id="@+id/fade_out"
android:layout_width="120dp"
android:layout_height="wrap_content"
android:layout_marginTop="130dp"
android:layout_toRightOf="@+id/fade_in"
android:text="Fade Out"
android:textAllCaps="false" />
</RelativeLayout>
android:interpolator="@android:anim/
linear_interpolator">
<alpha
android:duration="2300"
android:fromAlpha="0.2"
android:toAlpha="2.0" />
</set>
fade_out.xml:
AndroidManifest.xml File
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/
apk/res/android"
package="x.apps.fadeinout">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/
ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.
action.MAIN"/>
<category android:name="android.
intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>
</manifest>
Android Development with Kotlin ◾ 281
• <Menu>: The XML file’s root element that helps define the Menu
and holds various items.
• <item>: It is used to generate a single menu item. It also has nested
Menu> elements to form a submenu.
282 ◾ Mastering Kotlin: A Beginner’s Guide
• Small Icon: This is required and may be set using setSmallIcon ().
• Application Name: The system provides the application name.
• Time Stamp: This is the provided by system but can be changed.
• Large Icon: This is optional, may be configured with setLargeIcon ().
• Title: This is an optional title, which may be specified using setCon-
tentTitle ().
• Text: This is optional and may be set using setContentText ().
package com.gfg.progressnotificationdemo
import android.app.Application
import android.app.NotificationChannel
import android.app.NotificationManager
import android.os.Build
class App : Application(){
val channelId = "Progress Notification" as String
override fun onCreate(){
super.onCreate()
createNotificationChannels()
}
//Check if Android version is greater than 8.
private fun createNotificationChannels(){
if (Build.VERSION.SDK_INT >= Build.VERSION_
CODES.O) {
284 ◾ Mastering Kotlin: A Beginner’s Guide
MainActivity.kt:
package com.gfg.progressnotificationdemo
import android.app.PendingIntent
import android.content.Intent
import android.os.Bundle
import android.os.SystemClock
import android.view.View
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
import com.gfg.progressnotificationdemo.R.drawable
class MainActivity : AppCompatActivity(){
private lateinit var notificationManager:
NotificationManagerCompat
val channelId = "Progress Notification" as String
override fun onCreate(savedInstanceState: Bundle?){
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
//Create a Notification Manager
notificationManager =
NotificationManagerCompat.from(this)
}
Android Development with Kotlin ◾ 285
//notification.setContentText(progress.
toString()+"%")
//.setProgress(progressMax, progress, false)
//notificationManager.notify(1, notification.
build())
}
notification.setContentText("Download
complete")
.setProgress(0, 0, false)
.setOngoing(false)
notificationManager.notify(1,
notification.build())
}).start()
}
}
1. Manifests Folder
2. Java Folder
3. Resources (res) Folder
• Drawable Folder
• Layout Folder
• Mipmap Folder
• Values Folder
4. Gradle Scripts
Manifests Folder
The Manifests folder includes AndroidManifest.xml, which we will use
to create the Android application. This file provides information about
Android Development with Kotlin ◾ 287
our app, such as the Android version, metadata, the states package for the
Kotlin code, and other app components. It functions as a bridge between
the Android operating system and our application.
AndroidManifest.xml:
<category android:name="android.
intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Java Folder
The Java folder holds all of the Java and Kotlin source code (.java) files that
we write throughout app development and additional test files. When we
start a new Kotlin project, the class file MainActivity.kt is created auto-
matically under the package name “peeksforpeeks.myfirstkotlinapp,” as
seen below.
MainActivity.kt:
package peeksforpeeks.myapplication
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?)
288 ◾ Mastering Kotlin: A Beginner’s Guide
{
super.onCreate(savedInstanceState)
setContentView(C.layout.activity_main)
}
}
res/values folder: The values folder contains number of XML files that
define strings, dimensions, colors, and styles. The strings.xml file, which
includes the resources, is one of the most crucial.
<resources>
<string name="app_name">NameOfTheApplication</
string>
<string name="checked">Checked</string>
<string name="unchecked">Unchecked</string>
</resources>
CONCLUSION
In this chapter, we covered Android development in Kotlin where we also
covered how to create the project in Android Studio and install AVD. We
also learned Kolin’s animation, menus, progress notification, and project
folder structure.
Appraisal
fun main() {
var string: String1 = "Helloo, World!" //
defining variable
println("$string1")
}
The only compelling justification we’ve seen for using Java over Kotlin is
for total Android programming novices. Given that most Android docu-
mentation and examples have historically been written in Java, they might
be challenging. Converting Java to Kotlin with Android Studio, on the
other hand, is as simple as putting the Java code into a Kotlin file.
The benefits of Kotlin are compelling for practically everyone else
undertaking Android programming. A Java developer will typically spend
a few hours learning Kotlin – a modest price to pay to remove null refer-
ence issues, enable extension functions, support functional programming,
and add coroutines. The standard rough estimate implies a 40% reduction
in the number of lines of code when switching from Java to Kotlin.
Android Development
Kotlin is the recommended language for Android development because
it allows developers to write more concise, expressive, and secure code.
Android Studio, the official IDE for Android development, fully supports
it, so we can receive the same sort of code completion and type checking
to assist us in creating Kotlin code as we can with Java.
Because more people now access the Internet via mobile phones, most
companies must have a mobile presence. Because Android accounts for
more than 70% of the mobile phone market, Kotlin developers would be in
great demand even if Kotlin was solely used for Android development. It
may, however, be used for much more.
Amazon, and many more organizations have already replaced Java in their
server-side code with Kotlin.
Data Science
Data scientists have long used Java to crunch information, discover pat-
terns, and make predictions, so it seems to reason that Kotlin will find a
home in this field as well.
Data scientists can utilize all of the standard Java libraries that they are
accustomed to using in Java projects, but they must develop their code in
Kotlin. Jupyter and Zeppelin, two tools that many data scientists regularly
utilize for data visualization and exploratory study, support Kotlin.
the previous decade, which now stands at 73%. The reasons for learning
Kotlin over Java, for example, are self-evident.
Simple to Grasp
One of the significant considerations when learning a new language is its
complexity. Understanding and mastering Kotlin will be almost straight-
forward for anyone with prior development expertise. Kotlin’s syntax and
design are simple to grasp while still quite powerful. This is one of the
critical reasons why Kotlin has surpassed Java as the preferred language
for creating Android apps.
Extensions
Extension methods allow for adding functionality to existing classes with-
out completely rewriting them in Kotlin. This means we can use Kotlin’s
rich features without having to lose all of the skills we’ve acquired while
developing current apps. It enables the recovery of views from Activities,
Fragments, and Views in an incredibly smooth manner. It also generates
a local view cache.
that do arise are identified during the compilation process, giving it a sig-
nificant reliability advantage over Java.
Strong Support
Kotlin has been around for a long time despite its current popularity, and
developers have made the most of this. Support has been available, and
Kotlin is prospering with the flood of new developers, not to mention that
Google officially endorses it. Google announced formal Kotlin support at
Google I/O in May 2017. And the community is there to assist you in mak-
ing the most of it.
Multiplatform Kotlin
JetBrains just announced Kotlin Multiplatform in 2020, which is an exten-
sion of the language that allows it to be used for more than just Android
app development. Kotlin Multiplatform allows developers to create apps
for both iOS and Android using a single codebase. This has the potential
to be a game changer, propelling Kotlin to the forefront of programming
languages.
JOBS IN KOTLIN
Kotlin is in great demand, and all big corporations are using it to construct
online and mobile apps.
A Kotlin developer’s yearly compensation is roughly $130,000. However,
it varies depending on where you live. The following are some of the top
firms that use Kotlin:
• Google
• Amazon
• Netflix
• Pinterest
• Uber
• Trello
• Coursera
• Basecamp
• Corda
• JetBrains
298 ◾ Appraisal
• Using Kotlin, you can plan, create, and construct apps and software.
• Participating at all stages of the development cycle.
• When necessary, features are tested and modified.
• Ensure that designs adhere to the specifications specified.
• Writing code that is well-designed and efficient.
• Analyzing, testing, and aiding with application integration.
• Performing software analysis.
• Application and software troubleshooting.
• Managing the development of applications.
• Assisting in the continuous enhancement of apps.
• Investigating and recommending technologies.
• Optimizing apps and systems.
• Identifying areas for improvement.
• Code optimization.
• Introducing new features.
• Assisting with software upgrades.
Bibliography
Akhin, M., & Belyaev, M. (n.d.). Kotlin language specification. Kotlin Language
Specification; kotlinlang.org. Retrieved July 11, 2022, from https://kotlin-
lang.org/spec/introduction.html
Baeldung. (n.d.). Kotlin. Kotlin Java Interoperability. Retrieved July 11, 2022,
from https://www.baeldung.com/kotlin/java-interoperability
Basic types | Kotlin. (2022, July 11). Kotlin Help; kotlinlang.org. https://kotlin-
lang.org/docs/basic-types.html
Collections overview | Kotlin. (2022, July 11). Kotlin Help; kotlinlang.org. https://
kotlinlang.org/docs/collections-overview.html#collection-types
Comparator in Kotlin - GeeksforGeeks. (2019, July 30). GeeksforGeeks; www.
geeksforgeeks.org. https://www.geeksforgeeks.org/comparator-in-kotlin/
Control Flow Statements in Kotlin. (n.d.). CherCherTech; chercher.tech. Retrieved
July 11, 2022, from https://chercher.tech/kotlin/control-flow-kotlin
Dehghani, Ali. (n.d.). Kotlin. Operator Overloading in Kotlin. Retrieved July 11,
2022, from https://www.baeldung.com/kotlin/operator-overloading
Destructuring Declarations in Kotlin | raywenderlich.com. (n.d.). Destructuring
Declarations in Kotlin | Raywenderlich.Com; www.raywenderlich.com.
Retrieved July 11, 2022, from https://www.raywenderlich.com/22178807-
destructuring-declarations-in-kotlin
EPS Software Corp., Wei-Meng Lee, C. M. (n.d.). Introduction to Kotlin.
Introduction to Kotlin; www.codemag.com. Retrieved July 11, 2022, from
https://www.codemag.com/Article/1907061/Introduction-to-Kotlin
Equality checks in Kotlin (Difference between “==” and “===” Operators). (n.d.).
Equality Checks in Kotlin (Difference between “==” and “===” Operators);
www.tutorialspoint.com. Retrieved July 11, 2022, from https://www.tutori-
alspoint.com/equality-checks-in-kotlin-difference-between-and-operators
Equality evaluation in Kotlin - GeeksforGeeks. (2019, August 2). GeeksforGeeks;
www.geeksforgeeks.org. https://www.geeksforgeeks.org/equality-evaluation-
in-kotlin/#:~:text=The%20referential%20equality%20in%20Kotlin,the%
20same%20location%20in%20memory
Exceptions | Kotlin. (2022, July 11). Kotlin Help; kotlinlang.org. https://kotlinlang.
org/docs/exceptions.html
Get started with Kotlin/Native in IntelliJ IDEA | Kotlin. (2022, July 11). Kotlin
Help; kotlinlang.org. https://kotlinlang.org/docs/native-get-started.html
299
300 ◾ Bibliography
303
304 ◾ Index