Classes in Kotlin: inheritance, implementation, abstract and open (open)

- Andrés Cruz

En español
Classes in Kotlin: inheritance, implementation, abstract and open (open)

In the previous entry we talked about the main and secondary constructors, properties and constructor methods, we also gave an example on how to use the properties (attributes in Java), define the GET and SET methods of the properties established by default on the classes in Kotlin; all this in the previous entry:

Classes in Kotlin: empty classes, constructors and properties

Continuing the previous theme, in this post we will talk about inheritance, implementation, abstracts and a new type called open (open) on classes in Kotlin.

Open classes (Open class) and inheritance in Kotlin

The first thing we will cover here is how to create a class in Kotlin and how such classes are declared in Kotlin; classes in Kotlin are by default declared final, which means that we cannot inherit from a class we create like in this example:

class Padre
class Hija : Padre()

Because the Kotlin compiler would give us an error; classes in Kotlin inherit by default from a superclass called Any; therefore, the class named Parent inherits by default from the Any class:

class Padre // de manera implicita hereda de la clase Any

If we want to inherit from a class that we define, we must declare it as an "open class" or open class; this annotation has a behavior opposite to that of the endings in Java classes and therefore allows us to carry out inheritance, using the following annotation:

open class Padre
class Hija : Padre()

This is an important difference with Java, where we can inherit from a class without the need to incorporate a keyword that specifies that we want to be able to inherit from it; This is a very important principle in Kotlin to help us keep our classes organized, since by adding open in our classes we are indicating that we want to design said class so that it can be inherited, which in the end makes it easier to read the code in some way. application made with Kotlin, regardless of whether it is an application for Android, or for another platform; It is also important to note that we cannot inherit from multiple classes or multiple inheritance.

Declaring geometric classes and creating objects in Kotlin

This would be the essential here to inherit from classes, otherwise we can do the same as we do in other programming languages; for example, the following scheme is valid for declaring a series of classes to specify geometric shapes, which is what we will see next:

open class Forma(val nombre: String) {
   open fun area() = 0.0
}

class Circulo(nombre: String, val radius: Double): Forma(nombre)

In the example above we defined a class called Shape that would have the primitives to specify the geometric shapes, which in our case is just a name of the geometric shape, and a function that we override to specify the area of the geometric shape.

Then we create a Circle class and its constructor, which in the case of the circle we must add an extra parameter that is its radius:

class Circulo(name: String, val radius: Double)

Then, since we want our Circle class to inherit the Shape properties, we specify the inheritance by indicating the name of the class to inherit after indicating the colon, where we reference the Shape class constructor (it would be like using the super keyword in java):

class Circulo(name: String, val radius: Double): Forma(nombre)

Now we can override the area method for our circle:

To also override any property or method of the inherited class, we must specify the open keyword on that property or method.

open class Forma(val nombre: String) {
open fun area() = 0.0
}

class Circulo(nombre: String, val radio: Double): Forma(nombre) {
override fun area() = Math.PI * Math.pow(radio, 2.0)
}

fun main(args: Array<String>) {
val circulo = Circulo("Circulo", 4.0)
println(circulo.nombre)
println(circulo.radio)
println(circulo.area())
}

Abstract classes in Kotlin

Abstract classes pretty much follow the same principle as in other object-oriented programming languages like Java; abstract classes are those that have no implementation and the abstract keyword is used in classes for this purpose.

How can you remember in this case it is not necessary to specify a return value for our area method like we did before since it will be overridden in our child class:

abstract class Forma(val nombre: String) {
   abstract fun area(): Double

   fun printName(){
       println("el nombre es: ${nombre}")
   }
}

class Circulo(nombre: String, val radio: Double): Forma(nombre) {
   override fun area() = Math.PI * Math.pow(radio, 2.0)
}

fun main(args: Array<String>) {
   val circulo = Circulo("Circulo", 4.0)
   println(circulo.nombre)
   println(circulo.radio)
   println(circulo.area())
   println(circulo.printName())
}

We can use the reserved word in the methods (fun) to specify that the class that defines them override said methods, or we can implement some within the abstract class and in this way, be able to use them in the class that defines said abstract class.

As in any other language, we must override any method or property that contains the abstract keyword in the child class.

Interfaces in Kotlin

As the last object-oriented programming concept that we will cover in this post, interfaces are declared with the interface keyword; you should know that all methods are public and can be overridden; We can also define methods with body or content, which is a great advantage, since we don't have to repeat code in other classes and we can define it as a base in the interface.

A primary feature of interfaces is that they do not implement methods or constructors, which is a distinction from inheritance or abstract classes that we saw earlier.

The interfaces do not encapsulate data, they only define which are the methods that must be implemented in the classes that define it.

Therefore our example would be as follows:

interface Forma {
   fun area(): Double
   fun printName();
}

class Circulo(val nombre: String, val radio: Double): Forma {
   override fun area() = Math.PI * Math.pow(radio, 2.0)
   override fun printName(){}
}

fun main(args: Array<String>) {
   val circulo = Circulo("Circulo", 4.0)
   println(circulo.nombre)
   println(circulo.radio)
   println(circulo.area())
}

We can also define a default implementation in our interface:

interface Forma {
   fun area(): Double = 0.0
   fun printName();
}

You can consult the official documentation for more details: Kotlin: Classes and Inheritance; remember to consult other entries about Kotlin that we have in DesarrolloLibre from the Kotlin tag.

Andrés Cruz

Develop with Laravel, Django, Flask, CodeIgniter, HTML5, CSS3, MySQL, JavaScript, Vue, Android, iOS, Flutter

Andrés Cruz In Udemy

I agree to receive announcements of interest about this Blog.