Skip to content

Instantly share code, notes, and snippets.

@kezzico
Last active December 5, 2023 18:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kezzico/fab9dfafa316f19b90fbb6c255bd2166 to your computer and use it in GitHub Desktop.
Save kezzico/fab9dfafa316f19b90fbb6c255bd2166 to your computer and use it in GitHub Desktop.

KOTLIN CRASH COURSE

Variables

There are 2 types of variables in Kotlin. Variables declared with val are immutable. Whereas variables declared with var are mutable.

Kotlin can infer a Variable's type at compile time. Variables that cannot be inferred can be explicitly typed.

val x:Int = 2

Variables can be passed to functions. Variables passed to functions are called parameters. Functions parameters have a type, and an optional default value.

fun add(a: Int, b: Int = 0) = a + b

Loops and Branches

Control statements like IF and ELSE do not require a parenthesis. However, they follow the same syntax as other languages that take after C.

    if (number > 0) {
        println("Number is positive")
    } else if (number < 0) {
        println("Number is negative")
    } else {
        println("Number is zero")
    }

Loops use the for in syntax to iterate over objects in an array

    val fruits = arrayOf("Apple", "Banana", "Orange")

    println("Fruits:")
    for (fruit in fruits) {
        println(fruit)
    }
}

Loops that iterate for a given number of iterations use the for in until syntax

for (i in 0 until 100) {
    // Your code here using the loop variable 'i'
    println(i)
}

For quick declarations, a modified version of the ternary operator is available.

val x = 5
val y = 10

val max = if (x > y) x else y
println("The maximum value is: $max")

Constructors

The default constructor in Kotlin is defined in paranthesis as part of the class definition.

class Event(val dayOfWeek: String, val timeOfDay: Int) {
  private val participants: MutableList<String> = mutableListOf()
  
  init() {
    if dayOfWeek == "Tuesday" {
      participants.add('Lee')
    }
  }
    
    constructor(dayOfWeek: String) : this(dayOfWeek, 100)    
}
  

the init() function is always called. It is the code of the default constructor. Even if another constructor is added, the init() function will be called following the execution of the constructor.

Arrays

For mutable array's Kotlin uses the MutableList<> type.

val participants: MutableList<Person> = mutableListOf()
participants.add(lee);

Arrays can be quickly constructed using arrayOf, arrayOfNulls, and emptyArray

val fruits = arrayOf("Apple", "Banana", "Orange")

Other common array types include List and ArrayList.

Accessors and Mutators

Special functions called accessors give access to read a property of class. While mutators give access to change a class property. For example: getFoo() and setFoo(value).

As a convenience of Kotlin, all class properties have these methods by default.

class Example {
    var myProperty: String
}

For added flexibility, special mutator and accessor functions can be defined.

class Example {
    var myProperty: String
        get() = field
        set(value) {
            field = value
            // Additional code to run when the property is set
        }
}

The variable field is a reserved keyword refering to the field backing the property.

Note that there is no didSet or willSet equivalent in Kotlin.

Nullability

Kotlin, similar to Swift, discourages the use of null values.

Rules are as follow

Declaring a val with no initial value results in a compiler error.

val x:Int

Declaring a var with no initial value is allowed. However, if the var is accessed before being assigned a value, a compiler error will be produced.

Use the lateinit specifier to declare class properties that do not have an initial value. lateinit is a promise to the compiler, that a value will be set before accessing the property. Failure to do so will result in a null pointer exception.

note lateinit is different from force unwrapping var x:Int! in Swift. lateinit can only be used on class properties. While force unwrap from Swift can be used anywhere.

The not-null assertion operator (!!) in Kotlin is used to assert that an expression or variable is not null. When you use !!, you are telling the compiler to treat the expression as non-null, even if its type is nullable.

val nullableString: String? = "Hello"
val nonNullableString: String = nullableString!!

Strings

All Strings in Kotlin are double quoted. Single quotes are reserved for single characters.

var s = "my string"

Strings are concatenated using the + operator

var s1 = "hello, "
var s2 = "World."

println(s1+s2)

A Raw string makes escaping characters unecessary. It also alows for multiple lines of input to define a single string

val multiLineString = """
    This is a raw string
    that spans
    multiple lines.
"""

println(multiLineString)

Strings can have their leading and trailing whitespace removed using the .trimMargin() function.

Strings in Kotlin are compared lexicographically. When result is equal to 0 then the strings are identical.

val result = string1.compareTo(string2, ignoreCase = true)

if (result < 0) {
    println("$string1 comes before $string2")
} else if (result > 0) {
    println("$string1 comes after $string2")
} else {
    println("$string1 is equal to $string2")
}

Strings can be reference variables using the $ operator.

val foo = "World"

println("Hello, $foo")

val a = 1

val b = 2

println("$a + $b = ${a + b}")

Note*, values inserted into strings can be computed, but only if the value is known at compile time. This is to prevent complex computations from being performed inside a string.

Null Coalescing

Traditional nil coalescing can be achieved in Swift using this syntax:

let p = a ?? 1

However, Kotlin has more advanced nil coalescing. The programmer must identify the nullable part of the expression using the 'safe call' operator in conjunction with the 'elvis operator'. In the example, if 'a' is nil then the value of p will be 1.

let p = a?.foo ?: 1

Similarly, in Swift this would require a much more contrived line of code to achieve the same thing

Here is a more advanced example of the elvis operator.

val result = obj?.property1?.method1() ?: defaultValue

KEYWORDS

Simple Class

a class does not have a primary constructor or an init block, and it doesn't inherit from another class

Access Modifiers

Used to control the level of access to a property, function or class. Kotlin has the same access levels as Java

  • public(default)
  • private
  • protected
  • internal

EXAMPLES

REGEX

Use raw strings to avoid escaping

val regexPattern = Regex("""[A-Z]* """)
val regexPattern = Regex("\\d{3}-\\d{2}-\\d{4}") // Example: Social Security Number
val inputString = "123-45-6789"

if (regexPattern.matches(inputString)) {
    println("String matches the pattern")
} else {
    println("String does not match the pattern")
}

HTTP REQUEST

import okhttp3.*
import java.io.IOException

class HttpClient {

    fun makeHttpRequest(url: String, callback: (String?, Exception?) -> Unit) {
        val client = OkHttpClient()

        val request = Request.Builder()
            .url(url)
            .build()

        client.newCall(request).enqueue(object : Callback {
            override fun onResponse(call: Call, response: Response) {
                val responseBody = response.body?.string()
                callback(responseBody, null)
            }

            override fun onFailure(call: Call, e: IOException) {
                callback(null, e)
            }
        })
    }
}

fun main() {
    val httpClient = HttpClient()
    val url = "https://www.example.com"

    println("Making HTTP request...")
    
    httpClient.makeHttpRequest(url) { responseBody, exception ->
        if (exception != null) {
            println("HTTP request failed: $exception")
        } else {
            println("HTTP request successful. Response: $responseBody")
        }
    }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment