Is it right, that abstract classes are only control structures in OOP, respectively that I don't forget to implement a method in a sub class?
This is actually the responsibility of interfaces.
Abstract classes are for sharing the code, the logic or behavior between multiple subclasses. And because the behavior provided by the base class may require that some missing parts of the logic are provided by subclasses, we can declare a base class as abstract and declare abstract members in it - similarly to interfaces. "abstract" in this context basically means that the functionality is incomplete and can't be used straight away, without filling the gaps.
In practice, sharing of the code through subtyping is generally discouraged and therefore abstract classes are less popular nowadays than in the past. We learnt that it is usually better and easier to maintain if we share the code by composition of multiple separate classes than by subclassing (https://en.wikipedia.org/wiki/Composition_over_inheritance).
Edit: see this example:
abstract class AbstractDataHandler {
fun doSomething() {
// acquire data
processData(data)
// do something else with data
}
abstract fun processData(data: Data)
}
class MyDataHandler : AbstractDataHandler() {
override fun processData(data: Data) {
// process data
}
}
We have some kind of a data handler. At some point it has to perform some kind of data processing, but this processing should be different depending on the specific subclass. So AbtractDataHandler
can't perform the whole operation alone. It needs a way to invoke data processing step that is provided by the subclass. It defines this processing as an abstract function.
The same example could be implemented with composition instead:
interface DataProcessor {
fun processData(data: Data)
}
class DataHandler(private val processor: DataProcessor) {
fun doSomething() {
// acquire data
processor.processData(data)
// do something else with data
}
}
(In this specific case it would be probably more Kotlin-ish to not use an interface, but a function type.)
Also, abstract classes are common if we need to implement an interface and there is some very basic functionality that is the same across all implementations. For example, all implementations have to provide the same fields for storing the data. Then abstract class could provide these fields, but it does know nothing about implementing the rest of the interface, so most of functions remain abstract.