Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Kotlin: why use Abstract classes (vs. interfaces)?

I'm aware of two differences between Abstract classes and Interfaces in Kotlin:

  • An abstract class can have state (e.g. var...)
  • A class can implement multiple interfaces, but not multiple abstract classes.

Since Kotlin is a rather fresh language, I wonder why Abstract Classes were not abandoned? Interfaces seem superior tool, with a very little need for Abstract Classes.

To elaborate: Kotlin does support concrete function implementation in interfaces, e.g.:

interface Shiny {      fun shine(amount : Int)  // abstract function      fun reflect(s : String) { print ("**$s**") }  // concrete function  } 

Can someone provide a strong practical example of the need for Abstract Classes?

like image 976
Lior Bar-On Avatar asked Aug 10 '17 14:08

Lior Bar-On


People also ask

Why do we use abstract class in Kotlin?

A Kotlin abstract class is similar to Java abstract class which can not be instantiated. This means we cannot create objects of an abstract class. However, we can inherit subclasses from a Kotlin abstract class. A Kotlin abstract class is declared using the abstract keyword in front of class name.

Why do we need abstract class rather than interface?

An abstract class is used if you want to provide a common, implemented functionality among all the implementations of the component. Abstract classes will allow you to partially implement your class, whereas interfaces would have no implementation for any members whatsoever.

When should you use abstract class vs interface?

Abstract classes should be used primarily for objects that are closely related, whereas interfaces are best suited for providing a common functionality to unrelated classes. Interfaces are a good choice when we think that the API will not change for a while.

How is an abstract class different from an interface in Kotlin?

Kotlin interfaces are similar to abstract classes. However, interfaces cannot store state whereas abstract classes can. Meaning, interface may have property but it needs to be abstract or has to provide accessor implementations. Whereas, it's not mandatory for property of an abstract class to be abstract.


1 Answers

The practical side of abstract classes is that you can encapsulate a part of implementation that works with the state, so that it cannot be overridden in the derived classes.

In an interface, you can only define a property without a backing field, and an implementation class must override that property (with either a backing field or custom accessors).

Given that, you cannot define logic that stores some state in an interface in a reliable way: an implementation class might override the properties in an unexpected way.

Example:

interface MyContainer {     var size: Int      fun add(item: MyItem) {          // ...         size = size + 1     } } 

Here, we provide a default implementation for add that increments size. But it might break if an implementing class is defined like this:

class MyContainerImpl : MyContainer {     override val size: Int          get() = 0         set(value) { println("Just ignoring the $value") } } 

On contrary, abstract classes support this use case and thus allow you to provide some guarantees and contract for all their implementations: they can define some state and its transitions that will stay the same in a derived class.

Apart from that, abstract classes can have non-public API (internal, protected) and final members, whereas interfaces cannot (they can only have private members, which can be used in the default implementations), and all their default implementations can be overridden in the classes.

like image 132
hotkey Avatar answered Sep 24 '22 11:09

hotkey