Kotlin Starter Pack

romainbsl
2,771 views

Open Source Your Knowledge, Become a Contributor

Technology knowledge has to be shared and made accessible for free. Join the movement.

Create Content

This chapter will talk about how to work with classes in Kotlin, and what's great about them.

Classes

As in Java or C#, classes are declared with the keyword class

class Book {}

You're allowed to omit curly braces if class is empty

class Book
Constructors

In Kotlin, a class can have a primary constructor and many secondary constructors.

  • Primary constructor

A primary constructor is part of the class header declaration.

class Book constructor(author: String) {}

Any many cases constructor keyword can be omitted.

class Book(author: String) {}

Primary constructor can't contains any logic. To help with that you can declare an init block.

class Book(author: String){
  init {
    println("init block for Book authored by $author")
  }
}
// { autofold
fun main(args: Array<String>) {
  Book("Chuck Palahniuk")
}
// }
  • Secondary constructor

Sometimes, you may need to initialize your object in multiple ways

class Book(author: String) {
    constructor(author: String, publisher: Publisher): this(author) {
    publisher.books.add(this)
  }
}

class initialization

To initialize you don't need any new keyword, just call the constructor

val fightClub = Book("Chuck Palahniuk")
val kotlinInAction = Book("Dmitry Jemerov and Svetlana Isakova", Publisher("Manning"))
Properties

As in C#, Kotlin have properties to describe classes. You can make them either valor var.

class Person {
  val name: String
  val birthDate: LocalDate
  var address: Address
}

Under the hood, Kotlin handles Getters and Setters. But, you also can override those Getters and Setters.

var name: String
    get() = this.toString()
    set(value) {
      field = value
      println("name updated: $value")
    }

Inheritance

In Kotlin:

  • all types are derived from Any.
  • classes are final by default, that means if you need to inherit from a class, it has to be open.
open class Animal(val name: String)
class Dog(name: String): Animal(name)
class Cat: Animal {
  constructor(name: String): super(name)
  constructor(name: String, color: String): super(name)
}

As in other languages you can override methods super classes' methods. In opposition to Java, the override keyword is mandatory.

open class Animal(val name: String) {
  fun eat() {} // can't be overriden
  open fun walk() {} // can be overriden
}
class Dog(name: String): Animal(name) {
  override fun walk() {}
}

Data Classes

In every languages, when you want to create object that carry data, you always have to write boilerplate code to compare, print or even duplicate objects. To get rid of that, Kotlin introduce the data class concept.

According to the following snippet, in one line, the compiler will create extra members as:

  • equals() / hashCode()
  • toString()
  • copy()
1
2
3
4
5
6
7
8
9
10
11
12
data class Cat(val name: String, val color: String)
// { autofold
fun main(args: Array<String>) {
val felix = Cat("Felix", "White")
val loki = Cat("Loki", "Black/White")
println("felix prints: $felix")
println("felix's hashCode: ${felix.hashCode()}")
println("loki prints: $loki")
println("felix's hashCode: ${loki.hashCode()}")
println("Does felix == loki ? ${felix == loki}")
}
// }
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Tips: Since v1.1, data class can inherit from other classes, but still can't be inherited

Sealed Classes

Kotlin introduced an other type of class, sealeed class. A sealed class, is a class that can be inherit by a restricted class set. By definition, a sealed class is abstract, that means it can't be directly instantiate. All derived classes have to be in the same file than the sealed class.

sealed class ArithmeticExpression 
data class Const(val number: Double) : ArithmeticExpression()
data class Sum(val left: ArithmeticExpression, val right: ArithmeticExpression) : ArithmeticExpression()

Accordingto the below snippet, you should be able to evaluate an ArithmeticExpression without having to implement a fallback.

1
2
3
4
5
6
fun evaluate(expr: ArithmeticExpression): Double = when (expr) {
is ArithmeticExpression.Const -> expr.number
is ArithmeticExpression.Sum -> evaluate(expr.left) + evaluate(expr.right)
// else branch is not needed, because all possibilities are covered
}
// {...}
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

For more details on sealed class please check at the Simon Wirst's playground

Visibility

Finally, there is some differences between Kotlin and Java when it comes to visibility.

For the packages (top-level functions/properties)
  • By default, the visibility is public, which means that your declaration is visible from everywhere.
  • In the contrary, a declaration made private will be visible inside the file containing it.
  • In Kotlin, there is a new visibility modifiers, internal, set the declaration as visible everywhere in the same module.

there is no protected visibility modifiers for top-level declarations

For the classes
  • if you mark a class member as private, it will be visible inside this class only.
  • if you mark a class member as protected, it will be visible inside this class and subclasses
  • if you mark a class member as internal, it will be visible from any code inside this module (IntelliJ IDEA / Maven / Gradle...)
  • if you mark a class member as public, it will be visible everywhere.
Open Source Your Knowledge: become a Contributor and help others learn. Create New Content