fun StarWarsMovie.releaseYear(): Int {
val year = release_date.substring(0, 4)
return year.toInt()
}
val newHope = StarWarsMovie("A New Hope", 4, "1977-05-25")
val releaseYear = newHope.releaseYear()
println("The release year of A New Hope is $releaseYear")
In the above example, we’ve defined a new method on the class, called releaseYear()
. Note that we defined it directly on the existing class: StarWarsMovie.releaseYear()
. We can do this with our own classes, but also with classes imported from third-party libraries. The Kotlin documentation shows an example of adding a method to the standard library. (I’m a bit wary of this kind of monkey patching but it certainly shows Kotlin’s flexibility.)
Now, imagine we wanted StarWarsMovie
to be a subclass of a Movie
superclass. In Kotlin, we could do something like this:
open class Movie(val title: String, val releaseDate: String) {
open fun releaseYear(): Int {
val year = releaseDate.substring(0, 4) return year.toInt()
}
}
class StarWarsMovie(title: String, episodeId: Int, releaseDate: String) : Movie(title, releaseDate) {
val episodeId: Int = episodeId
}
The open
keyword indicates that a class or function is available for subclassing or overriding. In Java terms, Kotlin classes are final by default. Default public members and default final classes could be interpreted as subtle encouragement to prefer composition over inheritance. In the preceding example, we used constructor-based declaration for both StarWarsMovie
and Movie
. The colon in : movie
indicates extension, working similarly to Java’s extends
keyword.