Module 2 : Advanced Android Development
Syllabus:
Introduction to Kotlin: Basics of Kotlin, type conversions, comments, Kotlin operators,
variables in Kotlin, packages, visibility modifiers, control flow statements, Concept of OOPS
in Kotlin, classes in Kotlin, delegation and extension functions, the companion object.
[Link]
Introduction to Kotlin
Kotlin is a statically typed, general-purpose programming language developed by
JetBrains, which has built world-class IDEs like IntelliJ IDEA, PhpStorm, Appcode, etc.
It was first introduced by JetBrains in 2011 as a new language for the JVM.
Kotlin is an object-oriented language, and a better language than Java, but still fully
interoperable with Java code.
Kotlin is sponsored by Google, announced as one of the official languages for Android
Development in 2017.
Key Features of Kotlin
● Statically typed: Statically typed is a programming language characteristic that means the
type of every variable and expression is known at compile-time. Although it is a
statically typed language, it does not require you to explicitly specify the type of every
variable you declare.
● Data Classes: In Kotlin, there are Data Classes which lead to auto-generation of boilerplate
like equals(), hashCode(), toString(), copy(), getters/setters and much more.
These are called data classes, and they are marked with the data
keyword.
Kotlin automatically creates some useful functions for these classes, so
you don’t have to write them yourself.
● Concise: It drastically reduces the extra code written in other object-oriented programming
languages.
● Null Safety: It provides the safety from NullPointerExceptions by supporting nullability as
part of its system. Every variable in Kotlin is non-null by default.
[Link]
● Interoperable with Java: Kotlin runs on Java Virtual Machine(JVM) so it is totally
interoperable with java. We can easily access java code from Kotlin and Kotlin code from
Java.
● Functional and Object Oriented Capabilities: Kotlin has a rich set of many useful
methods which including,
○ higher-order functions,
○ lambda expressions,
○ operator overloading
○ lazy evaluation etc.
● Smart Cast: It explicitly typecasts the immutable values and inserts the value in its safe cast
automatically.
If we try to access a nullable type of String ( String? = "BYE") without a safe cast, it will
generate a compile error.
We use is or !is operator to check the type of variable, and compiler automatically casts the
variable to the target type.
Kotlin Equivalent with Smart Casting:
fun main() {
val str1: String? = "GeeksforGeeks"
val str2: String? = null
if (str1 is String) {
// Smart cast: No need for explicit casting
println("Length of string: ${[Link]}")
} else {
println("String is null")
Output:
Length of string: 13
[Link]
● Fast Compilation time: It has higher performance and a fast compilation time.
● Tool-Friendly: It has excellent tooling support. Any of the Java IDEs - IntelliJ IDEA,
Eclipse, and Android Studio can be used for Kotlin. We can also be run Kotlin program
from command line.
Advantages of the Kotlin language
Easy to learn: Kotlin is almost similar to java, If anybody worked in java then easily
understand kotlin in no time.
Kotlin is multi-platform: Kotlin is supported by all IDEs of java so you can write your
program and execute them on any machine which supports JVM.
Safe: It’s much safer than Java.
Interoperable: It allows using the Java frameworks and libraries in your new Kotlin
projects by using advanced frameworks without any need to change the whole project in Java.
Open Source: Kotlin programming language, including the compiler, libraries and all the
tooling is completely free and open source and available on github. Here is the link for
Github [Link]
Applications of Kotlin language
You can use Kotlin to build an Android Application.
Kotlin can also compile to JavaScript, making it available for the frontend.
It is also designed to work well for web development and server-side development.
Cross-Platform with Kotin Multiplatform.
Basics of Kotlin
Kotlin Syntax
Example
fun main() {
println("Hello World")
}
Kotlin Comments
Comments can be used to explain Kotlin code, and to make it more readable. It can also be used to
prevent execution when testing alternative code.
Single-line Comments
Single-line comments starts with two forward slashes (//).
Any text between // and the end of the line is ignored by Kotlin (will not be executed).
This example uses a single-line comment before a line of code:
Example
// This is a comment
println("Hello World")
This example uses a single-line comment at the end of a line of code:
Example
println("Hello World")
// This is a comment
Multi-line Comments
Multi-line comments start with /* and ends with */.
Any text between /* and */ will be ignored by Kotlin.
Example
/* The code below will print the words Hello World
to the screen, and it is amazing */
println("Hello World")
Kotlin Variables
Variables are containers for storing data values.
To create a variable, use var or val, and assign a value to it with the equal sign (=):
Syntax
var variableName = value
val variableName = value
Example
var name = "John"
val birthyear = 1975
println(name) // Print the value of name
println(birthyear) // Print the value of birthyear
The difference between var and val is that variables declared with the var keyword can be
changed/modified, while val variables cannot.
Variable Type
Unlike many other programming languages, variables in Kotlin do not need to be declared with a
specified type (like "String" for text or "Int" for numbers, if you are familiar with those).
To create a variable in Kotlin that should store text and another that should store a number, look at
the following example:
Example
var name = "John" // String (text)
val birthyear = 1975 // Int (number)
println(name) // Print the value of name
println(birthyear) // Print the value of birthyear
Kotlin is smart enough to understand that "John" is a String (text), and that 1975 is
an Int (number) variable.
However, it is possible to specify the type if you insist:
Example
var name: String = "John" // String
val birthyear: Int = 1975 // Int
println(name)
println(birthyear)
You can also declare a variable without assigning the value, and assign the value later.
However, this is only possible when you specify the type:
Example
This works fine:
var name: String
name = "John"
println(name)
Output John
Example
This will generate an error:
var name
name = "John"
println(name)
Output: demo_variables4.kt:2:7: error: this variable must either have
a type annotation or be initialized
var name
Kotlin Operators
Operators are used to perform operations on variables and values.
The value is called an operand, while the operation (to be performed between
the two operands) is defined by an operator:
Kotlin divides the operators into the following groups:
Arithmetic operators
Assignment operators
Comparison operators
Logical operators
Arithmetic Operators
Arithmetic operators are used to perform common mathematical operations.
Operato Examp
Name Description
r le
+ Addition Adds together two values x+y
Subtracts one value from
- Subtraction x-y
another
Multiplicatio
* Multiplies two values x*y
n
Divides one value from
/ Division x/y
another
% Modulus Returns the division remainder x%y
++ Increment Increases the value by 1 ++x
-- Decrement Decreases the value by 1 --x
Kotlin Assignment Operators
Assignment operators are used to assign values to variables.
In the example below, we use the assignment operator (=) to assign the
value 10 to a variable called x:
Example
var x = 10
The addition assignment operator (+=) adds a value to a variable:
Example
var x = 10
x += 5
A list of all assignment operators:
Operato Examp Same Try
r le As it
= x=5 x=5
x=x+
+= x += 3
3
-= x -= 3 x=x-3
x=x*
*= x *= 3
3
/= x /= 3 x=x/3
x=x%
%= x %= 3
3
Kotlin Comparison Operators
Comparison operators are used to compare two values, and returns
a Boolean value: either true or false.
Operato Examp Try
Name
r le it
== Equal to x == y
!= Not equal x != y
> Greater than x>y
< Less than x<y
Greater than or equal
>= x >= y
to
<= Less than or equal to x <= y
Kotlin Logical Operators
Logical operators are used to determine the logic between variables or values:
Operato Try
Name Description Example
r it
Logical x < 5 && x <
&& Returns true if both statements are true
and 10
|| Logical or Returns true if one of the statements is true x < 5 || x < 4
Logical Reverse the result, returns false if the result is
!
not true
Kotlin Type Conversion
Type conversion (also called Type casting) refers to changing the entity of one data type
variable into another data type. As we know Java supports implicit type conversion from
smaller to larger data types. An integer value can be assigned to the long data type.
Example:
public class TypecastingExample {
public static void main(String args[]) {
byte p = 12;
[Link]("byte value : "+p);
// Implicit Typecasting
// integer value can be assigned
// to long data type
long q = p;
}
}
But, Kotlin does not support implicit type conversion. An integer value can not be assigned
to the long data type.
var myNumber = 100
var myLongNumber: Long = myNumber
// Compiler error
// Initializer type mismatch: expected 'Long', actual 'Int
'.
In Kotlin, the helper function can be used to explicitly convert one data type to another data
type.
Example:
var myNumber = 100
var myLongNumber: Long = [Link]()
// compiles successfully
The following helper function can be used to convert one data type into another:
toByte()
toShort()
toInt()
toLong()
toFloat()
toDouble()
toChar()
Note: There is No helper function available to convert into boolean type.
Conversion from a larger to a smaller data type
var myLongNumber = 10L
var myNumber2: Int = [Link]()
Kotlin Program to convert one data type into another:
fun main()
{
println("259 to byte: " + ([Link]()))
println("50000 to short: " + ([Link]()))
println("21474847499 to Int: " + ([Link]()))
println("10L to Int: " + ([Link]()))
println("22.54 to Int: " + ([Link]()))
println("22 to float: " + ([Link]()))
println("65 to char: " + ([Link]()))
// Char to Number is deprecated in kotlin
println("A to Int: " + ('A'.toInt()))
}
Output:
259 to byte: 3
50000 to short: -15536
21474847499 to Int: 11019
10L to Int: 10
22.54 to Int: 22
22 to float: 22.0
65 to char: A
A to Int: 65
Visibility Modifiers in Kotlin
[Link]
In Kotlin, visibility modifiers are used to control the visibility of a class, its
members (properties, functions, and nested classes), and its constructors.
The following are the visibility modifiers available in Kotlin:
1. private: The private modifier restricts the visibility of a member to the
containing class only. A private member cannot be accessed from
outside the class.
2. internal: The internal modifier restricts the visibility of a member to
the same module. A module is a set of Kotlin files compiled together.
3. protected: The protected modifier restricts the visibility of a member
to the containing class and its subclasses.
4. public: The public modifier makes a member visible to any code. This
is the default visibility for members in Kotlin.
Note: If no visibility modifier is specified, Kotlin uses public by default.
1. Public Modifier
● In Kotlin, the default modifier is public.
● It is possibly the most frequently used modifier in the entire language and there
are additional restrictions on who can see the element being modified.
● Unlike Java, in Kotlin there is no need to declare anything as public – it is the
default modifier, if we don’t declare another modifier - public works the same in
Kotlin, as in Java.
● When we apply the public modifier to top-level elements - classes, functions or
variables declared directly inside a package, then any other code can access it.
● If we apply the public modifier to a nested element - an inner class, or function
inside a class - then any code that can access the container can also access this
element.
Access Scope:
● Accessible from any class or file
● Works at both top-level and member-level declarations
Example:
// public by default
class A {
val int1 = 10
fun display() {
println("Value: $int1")
fun main() {
val obj = A()
[Link]() // Accessible from anywhere
Here, Class A is accessible from anywhere in the entire code, the variable int1, and the
function display() are accessible from anything that can access classes A.
2. Private Modifier
● In Kotlin, private modifiers allow only the code declared inside the same scope,
access.
● It does not allow access to the modifier variable or function outside the scope.
● Unlike Java, Kotlin allows multiple top-level declarations in the same file - a
private top-level element can be accessed by everything else in the same file.
Access Scope:
● Accessible only within the same class or file
Example:
class A {
private val int = 5
fun show() {
println("Inside A: $int")
fun main() {
val obj = A()
println([Link]) // Error: Cannot access 'int': it is private in 'A'
[Link]() // Can be accessed
Output:
Cannot access 'int': it is private in 'A'
Here, Class A is only accessible from within the same source file, and the int variable is
only accessible from the inside of class A. When we tried to access int from outside the
class, it gives a compile-time error.
3. Internal Modifier
● In Kotlin, the internal modifier is a newly added modifier that is not supported by
Java.
● Marked as internal means that it will be available in the same module, if we try to
access the declaration from another module it will give an error.
● A module means a group of files that are compiled together.
Access Scope:
● Accessible from any file within the same module
● Not visible outside the module
Note: Internal modifier benefits in writing APIs and implementations.
Example:
internal class A {
internal val number = 100
internal fun display() {
println("Number is: $number")
Here, Class A is only accessible from inside the same module. The variable number
and function display() are only accessible from inside the same module.
4. Protected Modifier
● In Kotlin, the protected modifier strictly allows accessibility to the declaring class
and its subclasses.
● The protected modifier can not be declared at the top level.
● In the below program, we have accessed the int variable in the getvalue() function
of the derived class.
Access Scope:
● Accessible in the declaring class and its subclasses
● Not visible outside the class hierarchy
Example:
open class A {
protected val int = 10
class B : A() {
fun getValue() {
println("The value of integer is: $int") // Accessible in subclass
fun main() {
val obj = B()
[Link]()
println([Link]) // Error: Cannot access 'int': it is protected
Output:
Cannot access 'int': it is protected
control flow statements
[Link]
Kotlin if-else expression
A programming language uses control statements to control the flow of
execution of a program based on certain conditions. If the condition is true then
it enters into the conditional block and executes the instructions.
There are different types of if-else expressions in Kotlin:
● if statement
● if-else statement
● if-else-if ladder expression
● nested if expression
Below is the Kotlin program to find the greater value between two numbers
using an if-else expression.
fun main(args: Array<String>) {
var a = 50
var b = 40
// here if-else returns a value which
// is to be stored in max variable
var max = if(a > b){
print("Greater number is: ")
a
}
else{
print("Greater number is:")
b
}
print(max)
}
Output:
Greater number is: 50
Below is the Kotlin program to determine the largest value among the three
Integers.
import [Link]
fun main(args: Array<String>) {
// create an object for scanner class
val reader = Scanner(System.`in`)
print("Enter three numbers: ")
var num1 = [Link]()
var num2 = [Link]()
var num3 = [Link]()
var max = if ( num1 > num2) {
if (num1 > num3) {
"$num1 is the largest number"
}
else {
"$num3 is the largest number"
}
}
else if( num2 > num3){
"$num2 is the largest number"
}
else{
"$num3 is the largest number"
}
println(max)
}
Output:
Enter three numbers: 123 231 321
321 is the largest number
While loop
It consists of a block of code and a condition. First of all the condition is
evaluated and if it is true then execute the code within the block. It repeats until
the condition becomes false because every time the condition is checked before
entering into the block. The while loop can be thought of as repeating of if
statements.
Syntax
while(condition) {
// code to run
Kotlin program to print numbers from 1 to 10 using a while loop:
fun main(args: Array<String>) {
var number = 1
while(number <= 10) {
println(number)
number++;
}
}
Output:
1
10
Kotlin program to print the elements of an array using a while loop:
fun main(args: Array<String>) {
var names = arrayOf("Praveen","Gaurav","Akash","Sidhant","Abhi","Mayank")
var index = 0
while(index < [Link]) {
println(names[index])
index++
}
}
Output:
Praveen
Gaurav
Akash
Sidhant
Abhi
Mayank
Kotlin do-while loop
do-while loop working - First of all, the statements within the block are
executed, and then the condition is evaluated. If the condition is true, the block
of code is executed again. The process of execution of the code block is
repeated as long as the expression evaluates to true. If the expression becomes
false, the loop terminates and transfers control to the statement next to the do-
while loop. It is also known as a post-test loop because it checks the condition
after the block is executed.
Syntax
do {
// code to run
while(condition)
Kotlin program to find the factorial of a number using a do-while
loop
fun main(args: Array<String>) {
var number = 6
var factorial = 1
do {
factorial *= number
number--
}while(number > 0)
println("Factorial of 6 is $factorial")
}
Output
Factorial of 6 is 720
Kotlin for loop
In Kotlin, the for loop is equivalent to the foreach loop of other languages like
C#. Here for loop is used to traverse through any data structure that provides
an iterator. It is used very differently then the for loop of other programming
languages like Java or C. The syntax of the for loop in Kotlin:
Syntax
for(item in collection) {
// code to execute
In Kotlin, a for loop is used to iterate through the following because all of them
provide an iterator.
Table of Content
● Range Using a for loop
● Array using for loop
● string using for loop
● collection using for loop
Range Using a for loop
You can traverse through the Range because it provides an iterator. There are
many ways you can iterate through a Range. The 'in' operator is used in a for
loop to check value lies within the Range or not. The following programs are
examples of traversing the range in different ways, and 'in' is the operator to
check the value in the range. If the value lies between the range, then it returns
true and prints the value.
● Iterate through the range to print the values:
fun main(args: Array<String>)
{
for (i in 1..6) {
print("$i ")
}
}
Output
1 2 3 4 5 6
● Iterate through the range to jump using step 3:
fun main(args: Array<String>)
{
for (i in 1..10 step 3) {
print("$i ")
}
}
Output
1 4 7 10
● You can not iterate through a Range from top to down without
using DownTo :
fun main(args: Array<String>)
{
for (i in 5..1) {
print("$i ")
}
println("It prints nothing")
}
Output
It prints nothing
● Iterate through the Range from top to down with using downTo:
fun main(args: Array<String>)
{
for (i in 5 downTo 1) {
print("$i ")
}
}
Output
5 4 3 2 1
Iterate through the Range from top to down with using downTo and step 3:
fun main(args: Array<String>)
{
for (i in 10 downTo 1 step 3) {
print("$i ")
}
}
Output
10 7 4 1
Array using a for loop
An array is a data structure which contains same data type like Integer or
String. Array can be traversed using for loop because it also provides iterator.
Each array has a starting index and by default, it is 0.
There are the following can traverse the array:
● Traverse an array without using the index property
fun main() {
var numbers = arrayOf(1,2,3,4,5,6,7,8,9,10)
for (num in numbers){
if(num%2 == 0){
print("$num ")
}
}
}
Output
2 4 6 8 10
● Traverse an array using the index property
fun main() {
var planets = arrayOf("Earth", "Mars", "Venus",
"Jupiter", "Saturn")
for (i in [Link]) {
println(planets[i])
}
}
Output
Earth
Mars
Venus
Jupiter
Saturn
● Traverse an array using withIndex() Library Function
fun main(args: Array<String>) {
var planets = arrayOf("Earth", "Mars", "Venus", "Jupiter",
"Saturn")
for ((index,value) in [Link]()) {
println("Element at $index th index is $value")
}
}
Output
Element at 0 th index is Earth
Element at 1 th index is Mars
Element at 2 th index is Venus
Element at 3 th index is Jupiter
Element at 4 th index is Saturn
Kotlin when expression
❖ In Kotlin, when replaces the switch operator of other languages like Java.
❖ A certain block of code needs to be executed when some condition is
fulfilled.
❖ The argument of when expression compares with all the branches one by
one until some match is found. After the first match is found, it reaches
the end of the when block and executes the code next to the when block.
❖ Unlike switch cases in Java or any other programming language, we do
not require a break statement at the end of each case.
❖ In Kotlin, when can be used in two ways:
● when as a statement
● when as an expression
Using when as a statement with else
● when can be used as a statement with or without an else branch. If it is
used as a statement, the values of all individual branches are compared
sequentially with the argument, and the corresponding branch where the
condition matches. If none of the branches are satisfied with the
condition, then it will execute the else branch.
fun main () {
print("Enter the name of heavenly body: ")
var name= readLine()!!.toString()
//readLine-Reads one line of input from the keyboard (standard
input),!! means not null
when(name) {
"Sun" -> print("Sun is a Star")
"Moon" -> print("Moon is a Satellite")
"Earth" -> print("Earth is a planet")
else -> print("I don't know anything about it")
}
}
Output:
Enter the name of heavenly body: Sun
Sun is a Star
Enter the name of heavenly body: Mars
I don't know anything about it
Using when as a statement without else
● We can use when as a statement without else branch. If it is used as a
statement, the values of all individual branches are compared
sequentially with the argument and execute the corresponding branch
where condition matches. If none of the branches are satisfied with the
condition then it simply exits the block without printing anything to
system output.
fun main () {
print("Enter the name of heavenly body: ")
var name= readLine()!!.toString()
when(name) {
"Sun" -> print("Sun is a Star")
"Moon" -> print("Moon is a Satellite")
"Earth" -> print("Earth is a planet")
}
}
Output:
Enter the name of heavenly body: Mars
Process finished with exit code 0
Using when as an expression
● If it is used as an expression, the value of the branch whose condition is
satisfied will be the value of the overall expression.
● As an expression, when returns a value with which the argument
matches, and we can store it in a variable or print it directly.
fun main() {
print("Enter number of the Month: ")
var monthOfYear = readLine()!!.toInt()
var month= when(monthOfYear) {
1->"January"
2->"February"
3->"March"
4->"April"
5->"May"
6->"June"
7->"July"
8->"August"
9->"September"
10->"October"
11->"November"
12->"December"
else-> "Not a month of year"
}
print(month)
}
Output:
Enter number of the Month: 8
August
Kotlin Unlabelled break
● When we are working with loops and want to stop the execution of loop
immediately if a certain condition is satisfied, in this case, we can use
either break or return expression to exit from the loop.
● In this article, we will discuss learn how to use break expression to exit a
loop.
● When break expression encounters in a program it terminates to nearest
enclosing loop.
● There are two types of break expressions in Kotlin:
We are going to learn how to use unlabelled break expression in while,
do-while, and for loops.
Table of Content
● Use of an unlabelled break in a while loop
● Use of unlabelled break in do-while loop
● Use of unlabelled break in for loop
Use of an unlabelled break in a while loop
Unlabelled break is to used to exit the loop when it satisfies a specific condition
without checking the test expression. Then, transfers the control to the
following statement of while block.
Syntax of break in a while loop
while(test expression) {
// code to run
if(break condition) {
break
// another code to run
}
Kotlin program to find the sum of integers from 1 to 10.
fun main() {
var sum = 0
var i = 1
while(i <= Int.MAX_VALUE) {
sum += i
i++
if(i == 11) {
break
}
}
print("The sum of integers from 1 to 10: $sum")
}
Output:
The sum of integers from 1 to 10: 55
Use of an unlabelled break in a do-while loop
In a do-while loop, we can also use the break expression to exit the loop
without checking the test expression.
Syntax for break in do-while loop
do {
//code to run
if(break condition) {
break
while(test expression)
Kotlin program to print the elements of an array
fun main() {
var names =
arrayOf("Earth","Mars","Venus","Jupiter","Saturn","Uranus
")
var i = 0
do{
println("The name of $i th planet: "+names[i])
if(names[i]=="Jupiter") {
break
}
i++
}while(i<=[Link])
}
Output:
The name of 0 th planet: Earth
The name of 1 th planet: Mars
The name of 2 th planet: Venus
The name of 3 th planet: Jupiter
Use of an unlabelled break in a for loop
We can use a break expression while traversing the for loop within an array or
string.
Syntax of break in a for loop
for(iteration through iterator) {
// code to run
if(break condition){
break
}
Kotlin program to print a string upto a particular character
In the program below, we traverse the string to break at a particular position by
comparing the char value. First of all, initialize an array name with the value
"GeeksforGeeks". Then a for loop to traverse using an iterator i. It prints the
char value and compares it at each position with char 's'. If matches, then exit
the loop and transfer control to the following statement.
fun main() {
var name = "GeeksforGeeks"
for (i in name){
print("$i")
if(i == 's') {
break
}
}
}
Output:
Geeks
Kotlin labelled continue
Here, we will learn how to use continue in Kotlin. While working with a loop in
programming, sometimes, it is desirable to skip the current iteration of the
loop. In that case, we can use the continue statement in the program. continue
is used to repeat the loop for a specific condition. It skips the following
statements and continues with the next iteration of the loop.
There are two types of continuation in Kotlin.
As we know, unlabelled continue is used to skip the iteration of the nearest
closing loop, but labeled continue is used to skip the iteration of the desired
closing loop. It can be with the help of labels like inner@, outer@, etc. We just
need to write a label in front of the expression and call it using continue@abc.
We are going to learn how to use labeled continue in a while, do-while, and for
loop.
Use of labeled continue in a while loop
Labeled continue is used to skip the iteration of the desired block when it
satisfies a specific condition without checking the condition in the while loop. If
you mark the outer loop using the label outer@ and the inner loop using
inner@, then you can easily skip the specific condition using continue@outer in
the conditional block.
Syntax for labeled continue in a while loop
outer@ while(firstcondition) {
// code
inner@ while(secondcondition) {
//code
if(condition for continue) {
continue@outer
}
Kotlin program using labeled continue in a while loop
fun main() {
var num1 = 4
outer@ while (num1 > 0) {
num1--
var num2 = 4
inner@ while (num2 > 0) {
if (num1 <= 2)
continue@outer
println("num1 = $num1, num2 = $num2")
num2--
}
}
}
Output:
num1 = 3, num2 = 4
num1 = 3, num2 = 3
num1 = 3, num2 = 2
num1 = 3, num2 = 1
Concept of OOPS in Kotlin:
Classes in Kotlin:
● In Kotlin, classes and objects are used to represent objects in the real
world.
● A class is a blueprint for creating objects (a particular data structure),
providing initial values for state (member variables or fields), and
implementations of behavior (member functions or methods).
● An object is an instance of a class and has its own state and behavior.
You can create multiple objects from the same class, each with its own
unique state.
Here is an example of a class in Kotlin:
class Car {
var brand: String = ""
var model: String = ""
var year: Int = 0
fun getInfo(): String {
return "$brand $model, year $year"
}
}
fun main() {
val myCar = Car()
[Link] = "Toyota"
[Link] = "Camry"
[Link] = 2020
println([Link]())
}
Output:
Toyota Camry, year 2020
Kotlin program of creating multiple objects and accessing the property and
member function of class:
class Employee(val name: String, val age: Int, val gender: Char, val
salary: Double) {
fun showDetails() {
println("Name of the employee: $name")
println("Age of the employee: $age")
println("Gender of the employee: $gender")
println("Salary of the employee: $salary")
}
}
fun main() {
val emp1 = Employee("Praveen", 50, 'M', 500000.0)
[Link]()
val emp2 = Employee("Aliena", 30, 'F', 400000.0)
println("Name of the new employee: ${[Link]}")
}
Output:
Name of the employee: Praveen
Age of the employee: 50
Gender of the employee: M
Salary of the employee: 500000.0
Name of the new employee: Aliena
Problem Statement 1
Design and develop a Kotlin program to demonstrate object-oriented
programming concepts by creating a class with properties and a member
function. The program should:
1. Define a class Student with properties such as name, roll number,
and marks.
2. Include a member function to display student details.
3. Create multiple objects of the class in the main() function.
4. Access and display class properties and member functions using these
objects.
5. Display the details of all students and highlight the name of the top-
scoring student.
Program:
class Student(val name: String, val rollNo: Int, val marks: Int) {
fun displayDetails() {
println("Student Name: $name")
println("Roll Number: $rollNo")
println("Marks: $marks")
println()
}
}
fun main() {
// Creating multiple objects of Student class
val student1 = Student("Rahul", 101, 85)
val student2 = Student("Sneha", 102, 90)
val student3 = Student("Amit", 103, 78)
// Accessing member function
[Link]()
[Link]()
[Link]()
// Accessing property directly
println("Topper Student: ${[Link]}")
}
Output:
Student Name: Rahul
Roll Number: 101
Marks: 85
Student Name: Sneha
Roll Number: 102
Marks: 90
Student Name: Amit
Roll Number: 103
Marks: 78
Topper Student: Sneha
Problem Statement 2
Develop a Kotlin program to demonstrate object-oriented programming
concepts by modeling a bank account system. The program should:
1. Define a class BankAccount with properties such as account number,
account holder name, and balance.
2. Implement member functions to display account details and perform a
deposit operation.
3. Create multiple objects of the BankAccount class in the main()
function.
4. Access and display class properties and member functions using object
references.
5. Update and display the account balance after performing a deposit
operation.
Program:
class BankAccount(
val accountNumber: Int,
val accountHolder: String,
var balance: Double
){
fun showAccountDetails() {
println("Account Number: $accountNumber")
println("Account Holder: $accountHolder")
println("Balance: $balance")
println()
}
fun deposit(amount: Double) {
balance += amount
println("Amount Deposited: $amount")
println("Updated Balance: $balance")
println()
}
}
fun main() {
// Creating multiple objects of BankAccount class
val acc1 = BankAccount(1001, "Rohit", 15000.0)
val acc2 = BankAccount(1002, "Anita", 25000.0)
// Accessing properties
println("First Account Holder: ${[Link]}")
println()
// Accessing member functions
[Link]()
[Link]()
[Link](5000.0)
}
Output:
First Account Holder: Rohit
Account Number: 1001
Account Holder: Rohit
Balance: 15000.0
Account Number: 1002
Account Holder: Anita
Balance: 25000.0
Amount Deposited: 5000.0
Updated Balance: 20000.0
Kotlin Inheritance
● Kotlin supports inheritance, which allows you to define a new class based
on an existing class. The existing class is known as the superclass or
base class, and the new class is known as the subclass or derived
class.
● The subclass inherits all the properties and functions of the superclass,
and can also add new properties and functions or override the properties
and functions inherited from the superclass.
Syntax of inheritance:
open class baseClass (x:Int ) {
..........
}
class derivedClass(x:Int) : baseClass(x) {
...........
}
In Kotlin, all classes are final by default. To permit the derived class to inherit
from the base class, we must use the open keyword in front of the base class.
Here's a breakdown of the two key players in inheritance:
Superclass (Parent Class):
● The primary class contains the characteristics and behaviours that can
be overridden in sub-classes.
● They in turn form a guide that can be used to develop more detailed
subject-specific classes.
Subclass (Child Class):
● A class that is derived from another class and thus gets to inherit
properties and functions from that original class.
● It can create additional properties and functions that are specific to the
nature of the thing added.
● Enriches the superclass and builds a specialized new class from it.
Kotlin program of inheritance -
//base class
open class Employee( name: String,age: Int,salary : Int) {
init {
println("My name is $name, $age years old and earning $salary
per month. ")
//derived class
class webDeveloper( name: String,age: Int,salary : Int):
Employee(name, age,salary) {
fun website() {
println("I am website developer")
println()
//derived class
class androidDeveloper( name: String,age: Int,salary : Int):
Employee(name, age,salary) {
fun android() {
println("I am android app developer")
println()
//derived class
class iosDeveloper( name: String,age: Int,salary : Int): Employee(name,
age,salary) {
fun iosapp() {
println("I am iOS app developer")
println()
//main method
fun main() {
val wd = webDeveloper("Gennady", 25, 10000)
[Link]()
val ad = androidDeveloper("Gaurav", 24,12000)
[Link]()
val iosd = iosDeveloper("Praveen", 26,15000)
[Link]()
Output:
My name is Gennady, 25 years old and earning 10000 per month.
I am website developer
My name is Gaurav, 24 years old and earning 12000 per month.
I am android app developer
My name is Praveen, 26 years old and earning 15000 per month.
I am iOS app developer
Kotlin inheritance primary constructor:
● If the derived class contains a primary constructor, then we need to
initialize the base class constructor using the parameters of the
derived class.
● In the below program, we have two parameters in primary constructor
of base class and three parameters in derived class.
Kotlin program -
//base class
open class Employee(name: String,age: Int) {
init{
println("Name of the Employee is $name")
println("Age of the Employee is $age")
// derived class
class CEO( name: String, age: Int, salary: Double): Employee(name,age) {
init {
println("Salary per annum is $salary crore rupees")
fun main() {
CEO("Sunder Pichai", 42, 450.00)
Output:
Name of the Employee is Sunder Pichai
Age of the Employee is 42
Salary per annum is 450.0 crore rupees
Explanation of the above Program:
Here, we instantiate the derived class CEO and passed the parameter values
name, age and salary. The derived class local variables initialize with the
respective values and pass the variable name and age as parameters to the
Employee class.
The employee class prints the variable's names and values to the standard
output and transfers the control back to the derived class. Then, the derived
class executes the println() statement and exits.
Kotlin inheritance secondary constructor:
● If the derived class does not contain a primary constructor, we need to
call the base class secondary constructor from the secondary
constructor of the derived class using the super keyword.
● We also need to initialize the base class secondary constructor using
the parameters of the derived class.
In Kotlin, a class can have:
● Primary constructor → part of the class header
● Secondary constructor(s) → declared using
constructor(...)
Kotlin program:
//base class
open class Employee {
constructor(name: String,age: Int){
println("Name of the Employee is $name")
println("Age of the Employee is $age")
}
}
// derived class
class CEO : Employee{
constructor( name: String,age: Int, salary: Double): super(name,age) {
println("Salary per annum is $salary million dollars")
fun main() {
CEO("Satya Nadela", 48, 250.00)
Output:
Name of the Employee is Satya Nadela
Age of the Employee is 48
Salary per annum is 250.0 million dollars
Explanation of the above Program:
Here, we instantiate the class CEO and pass the parameter values to the
secondary constructor. It will initialize the local variables and pass to the base
class Employee using super(name,age).
Overriding Member functions and properties:
● If the base class and derived class contain a member function with the
same name, then we can override the base member function in the
derived class using the override keyword and also need to mark the
member function of the base class with an open keyword.
Kotlin program of overriding the member function :
// base class
open class Animal {
open fun run() {
println("Animals can run")
}
}
// derived class
class Tiger: Animal() {
override fun run() { // overrides the run method of base class
println("Tiger can run very fast")
}
}
fun main() {
val t = Tiger()
[Link]()
}
Output:
Tiger can run very fast
Similarly, we can override the property of the base class in the derived class.
Kotlin program of overriding the member property:
// base class
open class Animal {
open var name: String = "Dog"
open var speed = "40 km/hr"
}
// derived class
class Tiger: Animal() {
override var name = "Tiger"
override var speed = "100 km/hr"
}
fun main() {
val t = Tiger()
println([Link]+" can run at speed "+[Link])
}
Output:
Tiger can run at speed 100 km/hr
Calling the superclass implementation:
● We can also call the base class member functions or properties from
the derived class using the super keyword.
● In the below program we have called the base class property color and
function displayCompany() in the derived class using the super
keyword.
// base class
open class Phone() {
var color = "Rose Gold"
fun displayCompany(name:String) {
println("Company is: $name")
}
}
// derived class
class iphone: Phone() {
fun displayColor(){
// calling the base class property color
println("Color is: "+[Link])
// calling the base class member function
[Link]("Apple")
}
}
fun main() {
val p = iphone()
[Link]()
}
Output:
Color is: Rose Gold
Company is: Apple
Problem Statement:
Create a base class Employee with name and salary. Derive
a class Manager that adds a bonus and calculates total
salary.
open class Employee(val name: String, val salary: Double) {
open fun calculateSalary() {
println("Salary: $salary")
class Manager(name: String, salary: Double, val bonus: Double) :
Employee(name, salary) {
override fun calculateSalary() {
val totalSalary = salary + bonus
println("Manager Name: $name")
println("Total Salary: $totalSalary")
}
fun main() {
val manager = Manager("Riya", 50000.0, 10000.0)
[Link]()
Output:
2395 ms
Manager Name: Riya
Total Salary: 60000.0
Advantages of using inheritance in Kotlin:
1. Code Reusability: Inheritance allows you to reuse code from
existing classes, reducing the amount of code you have to write and
maintain.
2. Improved Abstraction: By creating a class hierarchy, you can create
an abstraction layer that makes your code more maintainable and
less prone to bugs.
3. Polymorphism: Inheritance allows you to create objects of different
types that have the same interface, which is a fundamental aspect
of object-oriented programming and enables polymorphic behavior.
Disadvantages of using inheritance in Kotlin:
1. Complexity: Inheritance can make your code more complex,
especially if you have many classes in a deep class hierarchy.
2. Coupling: Inheritance creates a tight coupling between the
superclass and the subclass, which can make it harder to change or
modify the superclass without affecting the subclass.
Kotlin Data Classes
[Link]
In Kotlin, we often create classes just to hold data. These are called data
classes, and they are marked with the data keyword. Kotlin automatically
creates some useful functions for these classes, so you don’t have to write
them yourself.
What Is a Data Class?
A data class is a class that holds data. Kotlin automatically provides useful
methods like:
1. equals() – to check if two objects are equal
2. hashCode() – used when storing objects in hash-based collections
3. toString() – to get a string version of the object
4. copy() – to copy an object with some modified values
Example:
data class Student(val name: String, val rollNo: Int)
When you create this class, Kotlin automatically gives it the above functions
using the primary constructor parameters (name and rollNo in this case).
Rules for Creating a Data Class -
To make sure data classes work correctly, Kotlin has some rules:
1. The primary constructor must have at least one parameter.
2. All primary constructor parameters must be marked with val or var.
3. A data class cannot be abstract, open, sealed, or inner.
4. A data class can only implement interfaces, not extend other classes.
Using toString()
toString() is a function that converts an object into a readable string.
In normal classes, you must write it yourself.
In data classes, Kotlin does it automatically.
The toString() function gives you a string showing all the values in the primary
constructor.
Example:
data class Person(val name: String, val roll: Int, val height: Int)
fun main() {
val man = Person("man", 1, 50)
println(man)
Output:
Person(name=man, roll=1, height=50)
Note: But if you define properties inside the class body (not in the constructor),
toString() won’t include them.
Example:
data class Person(val name: String) {
var height: Int = 70
fun main() {
val man = Person("manish")
println(man)
println([Link])
Output:
Person(name=manish)
70
Here height is not used by the toString() function .
how to use copy() in data classes.
data class User(
val id: Int,
val name: String,
val email: String,
val isActive: Boolean
)
fun main() {
val user1 = User(
id = 1,
name = "Alice",
email = "alice@[Link]",
isActive = true
)
// Copy and change only selected properties
val user2 = [Link]( name = "Bob", isActive = false)
println(user1)
println(user2)
}
Output:
User(id=1, name=Alice, email=alice@[Link], isActive=true)
User(id=1, name=Bob, email=alice@[Link], isActive=false)
What’s going on
● copy() is auto-generated for every data class
● It creates a new instance
● Any property you don’t pass keeps its original value
● Original object (user1) is untouched (immutability win 🏆)
Use of Equal()
data class User(
val id: Int,
val name: String
)
fun main() {
val user1 = User(1, "Alice")
val user2 = User(1, "Alice")
val user3 = User(2, "Bob")
println(user1 == user2) // true
println([Link](user2)) // true
println(user1 == user3) // false
}
Output:
true
true
false
For a data class, Kotlin auto-generates equals() that:
● Compares all properties in the primary constructor
● Uses structural equality, not reference equality
So two different objects with the same data are considered equal.
Delegation and Extension functions
[Link]
[Link] /
Delegation in Kotlin
Delegation = “Let someone else do the work for me.”
Instead of a class implementing all logic itself, it hands over (delegates)
the work to another object.
Kotlin gives built-in language support for delegation using the by
keyword.
Why delegation?
● Avoids code duplication
● Better than inheritance in many cases
● Follows composition over inheritance
● Makes code more flexible and reusable
● Delegation controls the allocation of power/authority from an instance
to another for any object.
● For classes and functions implementations, delegations can be used on
static as well as mutable relations between them.
● Inheritance implementation in classes and functions can be altered
with the help of delegation techniques and object-oriented
programming languages support it innately without any boilerplate
code.
● Delegation is used in Kotlin with the help of “by” keyword.
There are two types of delegation present in Kotlin:
• Explicit delegation: Supported by all object-oriented language and it is
done by passing a delegate(the one to be implemented) object to delegating
object (the one that will implement delegate object).
• Implicit delegation: Requires language-level support for the delegation
pattern.
Example:1
interface Printer {
fun printMessage()
} //This defines what needs to be done.
class ConsolePrinter : Printer {
override fun printMessage() {
println("Printing from ConsolePrinter")
} //This defines how it is done.
}
class SmartPrinter(printer: Printer) : Printer by printer //{
fun printMessage()
[Link]()
//“SmartPrinter implements Printer, but delegate the work to printer.”
fun main() {
val printer = ConsolePrinter()
val smartPrinter = SmartPrinter(printer)
[Link]()
}
Output:
Printing from ConsolePrinter
Let us discuss the concept of the delegation with the help of the examples:
Example 2:
As we know that in Kotlin, inheritance provides us with a permanent static
relationship between objects which are not mutable while delegation is, this
fact makes Delegation an extremely powerful alternative. In this example,
using Newfeature class we can implement delegation base class with new
features by delegating all its public members i.e mymessage and
messageline and we are using this implementation with the help of “by”
keyword.
// Kotlin program to illustrate the
// concept of delegation
interface delegation
{
fun mymessage()
fun mymessageline()
}
class delegationimplementation(val y: String) : delegation
{
override fun mymessage()
{
print(y)
}
override fun mymessageline()
{
println(y)
}
}
class Newfeature(m: delegation) : delegation by m
{
override fun mymessage()
{
print("GeeksforGeeks")
}
}
// Main function
fun main()
{
val b = delegationimplementation("\nWelcome, GFG!")
Newfeature(b).mymessage()
Newfeature(b).mymessageline()
}
Output:
GeeksforGeeks
Welcome, GFG!
Important rule:
If a delegated method is overridden, the override is used instead of
the delegated one.
So:
● mymessage() → uses Newfeature’s version
● mymessageline() → uses delegationimplementation’s version
Example 3:
In this example, we have one delegation base class with val value and
method “fun message()”. In the delegationimplementation class, we are
assigning value to this “fun message” and later from another class we are
using this implementation using “by” keyword to add a new statement with
same val value;
// Kotlin program to illustrate the
// concept of delegation
interface delegation
{
val value: String
fun mymessage()
}
class delegationimplementation(val y: String) : delegation
{
override val value = "delegationimplementation y = $y"
override fun mymessage()
{
println(value)
}
}
class Newfeatures(a: delegation) : delegation by a
{
override val value = "GeeksforGeeks"
}
fun main()
{
val b = delegationimplementation("Hello!GFG")
val derived = Newfeatures(b)
[Link]()
println([Link])
}
Output:
delegationimplementation y = Hello!GFG
GeeksforGeeks
Advantages:
1. It is a flexible, powerful as well as mutable method.
2. Multiple interfaces can be implemented with the help of the existing ones.
3. It is used to add new features and values to current implementations.
Kotlin extension function
Kotlin provides a powerful feature called Extension Functions that allows us to
add new functions to existing classes without modifying them or using
inheritance. This makes our code more readable, reusable, and clean.
What is an Extension Function?
An extension function is a function that is defined outside a class, but can be
called as if it were part of that class. We can use this feature on both user-
defined classes and library classes (like String, Int, etc.).
Declare an Extension Function
To declare an extension function, we must do it in the following way.
fun [Link](): ReturnType {
// function body
}
We use the class name followed by a dot (.), and then the name of the function.
Example:
class Circle(val radius: Double) {
fun area(): Double {
return [Link] * radius * radius
}
}
// Extension function
fun [Link](): Double {
return 2 * [Link] * radius
}
fun main() {
val circle = Circle(2.5)
println("Area of the circle is ${[Link]()}")
println("Perimeter of the circle is ${[Link]()}")
}
Output:
Area of the circle is 19.634954084936208
Perimeter of the circle is 15.707963267948966
Explanation:
Here, a new function is appended to the class using dot notation with class
[Link](), and its return type is Double. In the main function, an object
is created to instantiate the class Circle and invoked the function in println()
statement. When the member function is invoked it returns the area of a circle
and similarly, the extension function returns the perimeter of the circle.
Extension Functions on Library Classes
Kotlin not only allows the user-defined classes to be extended but also the
library classes can be extended. The extension function can be added to library
classes and used in a similar way as for user-defined classes. The following
example demonstrates an extension function created for a library class-
// Extension function defined for Int type
fun [Link](): Int {
return if (this < 0) -this else this
}
fun main() {
println((-4).abs())
println((4).abs())
}
Output:
4
Explanation:
We added a new function abs() to the Int type. It returns the absolute value of
an integer. So whether the number is -4 or 4, the output is the positive version:
4.
Extensions are resolved statically
One important point to note about the extension functions is that they are
resolved statically i.e which extension function is executed depends totally on
the type of the expression on which it is invoked, rather than on the type
resolved on the final execution of the expression at runtime. The following
example will make the above argument clear:
// Open class created to be inherited
open class A
// Class B inherits A
class B : A()
fun [Link]() = println("Called on A")
fun [Link]() = println("Called on B")
fun main() {
val obj: A = B() // Variable type → A
Actual object → B
This is classic polymorphism setup, but Extension
functions do not participate in polymorphism
[Link]() //What Kotlin sees at compile time obj is of type A
}
Output:
Called on A
Explanation:
If you are familiar with Java or any other object-oriented programming
language, you might notice in the above program, that since class B inherits
class A and the argument passed display function is an instance of class B. The
output should be 25 according to the concept of the dynamic method dispatch,
but since the extension functions are statically resolved, so the operation
function is called on type A. Hence the output is 10.
Nullable Receiver in Extension Functions
Extension functions can also be defined with the class type that is nullable. In
this case, when the check for null is added inside the extension function and the
appropriate value is returned.
Example:
// An extension function as a nullable receiver
fun String?.printName() {
if (this == null) {
println("Null")
} else {
println("Name is $this")
}
}
fun main() {
val name: String? = "Charchit"
val nullName: String? = null
[Link]()
[Link]()
}
Output:
Name is Charchit
Null
Explanation:
The receiver String? means the extension function can be called on a nullable
string. Inside the function, we check if this is null and act accordingly.
Extension Functions for Companion Objects
If a class contains a companion object, then we can also define extension
functions and properties for the companion object.
Example:
class MyClass {
companion object
}
fun [Link]() {
println("Function declared in companion object")
}
fun main() {
[Link]()
}
Output:
Function declared in companion object
We added a function showMessage() to the companion object of MyClass. We
can call it using the class name, just like we do with static methods in Java.
Companion Objects in Kotlin
In Kotlin, a companion object is used to define members that belong to the
class itself, not to its instances.
👉 Think of it like static members in Java.
● One companion object per class
● Accessed using the class name
● Can contain variables and functions
Example:
class MyClass {
companion object {
fun showMessage() {
println("Hello from Companion Object")
}
}
}
fun main() {
[Link]()
}
Output
Hello from Companion Object
Explanation
● showMessage() belongs to MyClass
● No object creation needed
● Called directly using [Link]()
Companion Object with Variables
class Counter {
companion object {
var count = 0
fun increment() {
count++
}
}
}
fun main() {
[Link]()
[Link]()
println([Link])
}
Output
2
Packages in Kotlin
[Link]
1. What is a Package in Kotlin?
A package in Kotlin is a namespace that groups related declarations together,
such as:
● classes
● interfaces
● functions
● properties
Packages help:
● organize large projects
● avoid name conflicts
● improve code readability and maintainability
👉 Similar to folders, but logically, not strictly physically.
2. Declaring a Package
In Kotlin, a package is declared using the package keyword at the top of the
file.
package [Link]
Rules:
● Must be the first statement in the file (except comments)
● One file → one package
● File name does not have to match the package name
3. Default Package
If no package is declared:
● The file belongs to the default package
● Declarations in the default package cannot be imported
⚠️Not recommended for real projects because it limits reuse.
4. Package Naming Convention
Kotlin follows reverse domain naming, similar to Java:
[Link]
Example:
package [Link]
Guidelines:
● All lowercase
● No special characters
● Avoid underscores unless necessary
5. Importing Packages
To use declarations from another package, you must import them.
Importing a single class/function
import [Link]
Importing multiple items (wildcard)
import [Link].*
6. Import Aliases
If two packages contain classes with the same name, aliases prevent conflicts.
import [Link]
import [Link] as LibDate
Usage:
val date1 = Date()
val date2 = LibDate()
7. Visibility and Packages
Kotlin has four visibility modifiers:
Modifier Accessible within same
package?
public Yes (default)
internal Yes (within same module)
protected Not directly (only
subclasses)
private No (file-level only)
8. Multiple Files in One Package
Multiple files can belong to the same package, even if they are in different
directories.
// [Link]
package [Link]
// [Link]
package [Link]
They can access each other’s public declarations directly.
9. Packages vs Directories
Package Directory
Logical grouping Physical folder
Declared in code Created in file
system
Can differ from folder IDE usually aligns
structure them
📌 Best practice: match package structure with directory structure.
10. Kotlin Standard Packages
Some commonly used built-in packages:
Package Purpose
kotlin Basic types (Int,
String, etc.)
[Link] Lists, Sets, Maps
ections
[Link] Input/output
[Link] String operations
[Link] Mathematical functions
These are imported automatically.
11. Example Program Using Packages
File: [Link]
package [Link]
fun add(a: Int, b: Int): Int {
return a + b
}
File: [Link]
package [Link]
import [Link]
fun main() {
println(add(3, 4))
}
12. Advantages of Using Packages
● Prevents name clashes
● Improves code organization
● Encourages modular design
● Makes large applications manageable
● Helps in access control
13. Key Exam Points (Quick Revision)
● Package declared using package keyword
● Default package cannot be imported
● Kotlin has no package-private
● Import aliases resolve naming conflicts
● One file belongs to only one package
Problem Statement
Write a Kotlin program to demonstrate a companion object with
variables and functions.
Create a class Student with:
● Instance variables: name and marks
● A companion object that:
○ Stores the college name
○ Counts the total number of students
○ Contains a function to display college details
Each time a student object is created, the student count should
increase.
Display student details along with shared college information.
class Student(val name: String, val marks: Int) {
init {
studentCount++
}
fun displayStudent() {
println("Name: $name")
println("Marks: $marks")
}
companion object {
var collegeName = "ABC Engineering College"
var studentCount = 0
fun displayCollegeInfo() {
println("College Name: $collegeName")
println("Total Students: $studentCount")
}
}
}
fun main() {
val s1 = Student("Arjun", 85)
val s2 = Student("Meera", 92)
[Link]()
println()
[Link]()
println()
[Link]()
}
Output:
2494 ms
Name: Arjun
Marks: 85
Name: Meera
Marks: 92
College Name: ABC Engineering College
Total Students: 2