I'm aware of two differences between Abstract classes and Interfaces in Kotlin:
var
...)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?
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.
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.
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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With