No history yet

Kotlin Basics

Welcome to Kotlin

Kotlin is a modern, statically typed programming language that's concise, safe, and fully interoperable with Java. It's the preferred language for Android development, but it's also used for web development, server-side applications, and more. Its clean syntax lets you express ideas with less code.

Let's start with the classic "Hello, World!" program. Every Kotlin application has a main entry point, which is a function called main. A function is a block of code designed to perform a particular task. We use the fun keyword to declare one.

fun main() {
    println("Hello, Kotlin!")
}

The println() function prints the text inside the parentheses to the console, followed by a new line. It's a simple way to see the output of your code.

Variables and Data Types

In programming, we use variables to store information. Kotlin has two keywords for declaring variables: val and var.

  • val is for variables whose value never changes. Think of it as a constant. You can't reassign a value to a val after it's been initialized.
  • var is for variables whose value can be changed. You can reassign new values to it as many times as you want.

It's a good practice to use val whenever possible. This makes your code safer and easier to reason about.

Prefer val over var. It helps prevent accidental changes to your data.

Variables can hold different types of data. Some basic types include:

  • Int: for whole numbers (e.g., 10, -5, 0)
  • Double: for decimal numbers (e.g., 3.14, -0.001)
  • Boolean: for true or false values
  • String: for text (e.g., "Hello")
  • Char: for a single character (e.g., 'A')

Kotlin has excellent type inference, meaning it can often figure out the type of a variable on its own, so you don't always have to declare it explicitly.

// Kotlin infers the type from the value
val language = "Kotlin"       // Inferred as String
var year = 2024              // Inferred as Int
val isAwesome = true         // Inferred as Boolean

// You can also declare the type explicitly
val pi: Double = 3.14159

year = 2025 // This is fine, since year is a 'var'

// A neat feature is string templates
println("$language was introduced in 2011.")
println("Is it awesome? $isAwesome")

Controlling the Flow

Code doesn't always run straight from top to bottom. We often need to make decisions or repeat actions. This is called control flow.

For decisions, we use if-else statements. If a certain condition is true, one block of code runs; otherwise, another block runs. In Kotlin, if can also be used as an expression, meaning it can return a value.

val score = 85

if (score >= 90) {
    println("Excellent!")
} else if (score >= 70) {
    println("Good job.")
} else {
    println("Keep practicing.")
}

// Using 'if' as an expression
val grade = if (score >= 90) "A" else "Not an A"
println("Grade: $grade")

For more complex branching, Kotlin provides the when expression. It's like a more powerful version of the switch statement found in other languages. It checks a value against a series of conditions.

val day = 3

val dayName = when (day) {
    1 -> "Sunday"
    2 -> "Monday"
    3 -> "Tuesday"
    4 -> "Wednesday"
    5 -> "Thursday"
    6 -> "Friday"
    7 -> "Saturday"
    else -> "Invalid day"
}

println("It's $dayName.")

To repeat actions, we use loops. The for loop is great for iterating over a collection of items, like a range of numbers.

// This will print numbers 1 through 5
for (i in 1..5) {
    println(i)
}

The while loop continues to run as long as a certain condition is true.

var i = 5
while (i > 0) {
    println("Countdown: $i")
    i-- // Decrement i by 1
}

Functions and Lambdas

Functions are reusable blocks of code that perform a specific task. We've already seen the main function. Functions help organize code and make it more readable.

A function is defined with the fun keyword, followed by the function name, a list of parameters in parentheses, and an optional return type. If a function doesn't return anything meaningful, its return type is Unit, which can be omitted.

// A simple function with two parameters and a return type
fun add(a: Int, b: Int): Int {
    return a + b
}

// A function that doesn't return a value (Unit is implicit)
fun greet(name: String) {
    println("Hello, $name!")
}

// Calling the functions
val sum = add(5, 3)
println("Sum: $sum")
greet("Alice")

Kotlin also has first-class support for functional programming. A key concept here is the lambda expression, which is essentially an anonymous function—a function without a name. Lambdas are very useful for passing small chunks of behavior as arguments to other functions.

A lambda expression is a function you can treat like a variable. You can pass it around, store it, and execute it later.

// A list of names
val names = listOf("anna", "brian", "charlie")

// We can use a lambda with the 'forEach' function
// to perform an action for each name in the list.
// The lambda is the code inside the curly braces { }.
names.forEach { name ->
    println(name.capitalize())
}

Classes and Objects

Kotlin is an object-oriented programming (OOP) language. The central idea of OOP is to bundle data and the functions that operate on that data into a single unit called an object.

The blueprint for creating an object is a class. A class defines the properties (data) and methods (functions) that its objects will have.

class Dog(val name: String, val breed: String) {
    // A method (a function inside a class)
    fun bark() {
        println("$name says: Woof!")
    }
}

fun main() {
    // Create an object (an instance) of the Dog class
    val myDog = Dog("Buddy", "Golden Retriever")

    // Access its properties
    println("${myDog.name} is a ${myDog.breed}.")

    // Call its methods
    myDog.bark()
}

Sometimes, you want to create a new class that builds upon an existing one. This is called inheritance. The new class, or subclass, inherits properties and methods from the original class, or superclass. To allow a class to be inherited from, you must mark it with the open keyword.

// The 'open' keyword allows this class to be extended
open class Animal(val name: String) {
    open fun makeSound() {
        println("Some generic animal sound")
    }
}

// Cat inherits from Animal
class Cat(name: String) : Animal(name) {
    // 'override' indicates this method replaces the parent's version
    override fun makeSound() {
        println("$name says: Meow!")
    }
}

fun main() {
    val myCat = Cat("Whiskers")
    myCat.makeSound() // Calls the overridden method
}

Finally, an interface defines a contract that classes can implement. It contains definitions for a set of related functionalities. A class that implements an interface must provide an implementation for its methods. A class can inherit from only one superclass, but it can implement multiple interfaces.

interface Clickable {
    fun onClick() // Abstract method to be implemented
}

class Button(val label: String) : Clickable {
    override fun onClick() {
        println("'$label' button was clicked!")
    }
}

fun main() {
    val loginButton = Button("Login")
    loginButton.onClick()
}

You now have a solid grasp of the building blocks of Kotlin. These fundamentals—variables, control flow, functions, and classes—are the foundation for writing any Kotlin application, including powerful Android apps.

Quiz Questions 1/5

In Kotlin, what is the primary difference between declaring a variable with val and var?

Quiz Questions 2/5

What is the keyword used to declare a function in Kotlin, and what is the name of the main entry point for a standard application?