Interfaces
In Kotlin, interfaces and classes are public by default. There is also no implements
or extends
keyword in Kotlin - instead these are delineated with a :
, so class A : B
.
interface Time {
fun setTime(hours: Int, mins: Int = 0, secs: Int = 0)
fun now(): Time
}
class YetiTime : Time {
override fun setTime(hours: Int, mins: Int, secs: Int) {}
}
When implementing a class in Kotlin, you have to use the override
keyword for any functions you are duplicating from the implementation. This is to tell the compiler that you are not trying to rename the method or that it was a mistake, that you are, in fact, overriding the implementation.
Like in Java8, we can implement default methods in Kotlin.
interface Time {
...
fun later(): Time = setTime(time.hours + 1)
}
If we want to implement multiple interfaces, then we would use the format class A : B, C
.
In the overridden methods, we must choose which method is being implemented from one of the interfaces, such as super<B>.doSomething() {}
Actual Classes
There are some differences between Kotlin classes and Java classes. Although, under the covers they are complied to the same, when writing in Kotlin there are several syntax differences.
In addition to being public
by default, classes are also final
by default. Methods are also final by default, so you can’t override functions unless it’s explicitly allowed. To allow a class or function to be overridden, we have to use the open
keyword - open class
or open fun
. This forces us to look at the structure and behavior of our classes and functions.
Abstract classes are open by default, but the methods inside an abstract class are still final. You could also use the abstract
keyword on functions, but you would need to provide either a default implementation or a define a new one in the class it’s implemented.
Kotlin doesn’t not have package-level visibility rules like Java, so there is not a package-private
setting. It does, however, have a concept of internal
classes. This would limit the visibility of the class to its module. Kotlin also supports private
and protected
, just not package private.
Sealed Classes, or Super Enums
Besides abstract classes and modifiers, like in Java, but Kotlin also supports sealed classes. Sealed Classes are used to restrict class Hierarchies; in many ways these can be seen as “enums on steroids.” To create a sealed class, we use the sealed
keyword:
sealed class Event {
class Depart(id: Int, to: String) : Type()
class Arrive(id: Int, from: String) : Event()
}
Only the classes defined within a sealed class can derive from that class, so this tightly controls what classes can exist within our code.
Sealed classes also introduce the when
statement that allows us to handle the different classes derived from the sealed class.
fun handleEvent(e:Event) =
when(e) {
is Depart -> print(e.to)
is Arrive -> print(e.from)
}
Within a when statement, there’s not an else
or default
available because we should know all the derived classes from the sealed class and be able to handle them. So instead of using a switch statement with enums, we can handle similar situations with a sealed class.