Skip to content

Instantly share code, notes, and snippets.

@radstevee
Created April 2, 2025 06:49
Show Gist options
  • Save radstevee/66bbf1fa43945eb734907a5047ef25f8 to your computer and use it in GitHub Desktop.
Save radstevee/66bbf1fa43945eb734907a5047ef25f8 to your computer and use it in GitHub Desktop.
Kotlin syntax cheatsheet

Kotlin Syntax Cheatsheet

This guide will help you understand kotlin's syntax.

Note that this guide does not cover any multiplatform aspects, but rather, the JVM platform. This guide also assumes that you have good knowledge of Java.

TODO:

  • lambdas

Functions

A function can be declared with the fun keyword and an optional access modifier before it.

fun hello() {
}

To return something, we can specify the return type before the opening brace like this:

fun hello(): String {
}

Now, let's return a string:

fun hello(): String {
  return "Hello!"
}

Type arguments

Type arguments, also referred to as generics can be passed into a function after the fun keyword:

fun <T> hello(value: T): String { ... }

We can specify type bounds using a colon here, for example, we don't want any nullable types (we will cover those later on), by adding a bound to the Any class:

fun <T : Any> hello(value: T): String { ... }

This will not accept any nullable types:

val nullable: Int? = null
val int: Int = 0

hello(nullable) // will not compile
hello(int) // compiles!

Inline functions

Inline functions are special functions that will have their body inline at compilation time. This is usually used for performance optimizations. Another benefit of inline functions are reified type parameters. They allow us to get the class of a type parameter if we mark it as reified:

inline fun <reified T> hello(value: T) {
  return T::class.simpleName!!
}

Variable declarations

As we already did above, you can declare immutable variables with the val keyword, and, optionally, specify the type. For mutable variables, you use var.

Access modifiers

Access modifiers can be added to any non-local declaration (except virtual members).

Kotlin has four access modifiers:

  • public: You usually don't need to explicitly add public to a declaration if not using the explicit API mode.
  • private
  • protected

Now, these are the ones we know from Java.

Let's see the fourth one, internal:

internal marks a declaration as internal to the current module, making it inaccessible from API users, but accessible for your implementation.

Classes

Classes are declared with the class keyword.

If we want to create a very basic, empty class, we can do it like such:

class VeryBoringClass

Notice how we don't need to use curly braces for the body here, since there is none?

Constructors

Kotlin classes have two types of constructors: Primary ones and secondary ones.

The primary constructor is declared after the class name with parenthesis:

class NotSoBoringClass()

Then we can pass in arguments. There's again, two types of arguments: Constructor arguments and fields. Constructor arguments are arguments passed in to the constructor only visible for itself and local variable initializers. They can be added to a constructor with the name: Type parameters. Then, we have fields, which are specified just like regular variable declarations:

class MyClass(
  constructorParameter: Int,
  val field: String
)

Fields in a constructor can also have access modifiers.

Classes are final by default and thus non-extendable. If you want your class to be extendable, use the open modifier.

This also applies to functions and fields.

Superclasses and interface implementation

To implement an interface or extend a superclass, you can use a colon after your primary constructor and declare the class or interface.

If you are extending an abstract class, you will need to call its constructor:

class ClassWithSuper(name: String) : SomeSuper(name)

class InterfaceImplementation : MyInterface

To override an implementation of something, you can use the override keyword.

Abstract classes

Abstract classes are classes declared with the abstract modifier and can have abstract fields and functions, also declared with the abstract modifier. There isn't much to cover here since beside from this, they aren't very different from regular classes.

Enum classes

Enum classes are classes declared with the enum class keyword. They cannot have type parameters. Enums allow you to specify a set of non-extendable values which are enumerated:

enum class CoffeeMachineState {
  IDLE, BREWING, FINISHED
}

Kotlin enums allow for both the SCREAMING_SNAKE_CASE and the PascalCase naming conventions.

Interfaces

Interfaces can be declared with the interface keyword and allow for virtual member functions and fields.

You can declare a virtual function like this:

interface CoffeeMachine {
  fun startBrewing()
  fun stopBrewing(): BrewResult
  var currentState: CoffeeMachineState
}

For default functions, you can do the same, but with a function body.

Objects

Kotlin has a special type of "classes" called objects, which are static singleton classes. These can do anything a regular class can, except have type parameters and a constructor. To create an object, you use the object keyword. For accessing an object, you just use its name. All fields and functions act like static fields/methods in the syntax.

Companion objects

You can think of companion objects like static declarations in classes. They are a regular object and can even have a different name. They can also extend and implement things, just like regular objects.

Let's create a companion for our CoffeeMachine interface:

interface CoffeeMachine {
  fun startBrewing()
  fun stopBrewing(): BrewResult
  var currentState: CoffeeMachineState

  companion object {
    fun basic(): CoffeeMachine {
      TODO()
    }
  }
}

This allows us to call CoffeeMachine.basic() to get a basic implementation of a CoffeeMachine.

Type system

Nullable types

Nullable types are types suffixed with a question mark. These allow us to use the ?. null-chaining operator to call a function on the value if it is not null, like this:

fun hello(list: List<String>?) {
  list?.map { str -> str.uppercase() }?.let(::println)
}

This will chain these calls if the provided list is not null:

  • maps the strings to uppercase
  • prints the list to a string

Special types

Kotlin has a couple of special types:

Any

You can think of Any as Java's Object type. Every class, interface and enum extends it.

Enum

Every enum class extends the Enum<E> type.

Unit

Unit is an object similar to Java's void.

Nothing

Nothing is a very special type. It marks a function that will never return anything. This is different from Unit in the sense that it will never even reach any return statement. This can only apply to functions that will always throw exceptions.

We saw this previously with the TODO function. This is its implementation:

fun TODO(): Nothing {
  throw NotImplementedError()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment