As I’m trying about open class tutorials, I’ve realized something. I have to override function that I’ve added into open class. But there is a confusing think when I’ve overriden this function.
open class Anything{
open fun Func(){
println("Func function has started.")
}
}
class DoSomething:Anything(){
override fun Func(){
super.Func() //calls from Anything open class
}
}
Isn’t there recursion following override?
And if we can call the function with super keyword from Anything class, why we use override?
No, in that special case the base implementation is called no matter what.
Well if that’s all the code, then doesn’t make a lot of sense, but probably it’s an example; usually when you ovveride a function you execute other code before or after calling the base implementation. At time you don’t even call the base class’ implementation
My guess is that you don’t quite understand how override or dynamic dispatch (the technical term for how a function is started on a class instance) works.
Imagine you aren’t allowed to use inheritance but you still want to use it as a feature or something similar. In that case you might do something like this.
enum class AnimalType {
AnyAnimal,
Dog,
Cat
}
class Animal {
val type: AnimalType
fun makeSound() {
when(type) {
AnimalType.Dog -> makeSoundDog()
AnimalType.Cat -> makeSoundCat()
AnimalType.AnyAnimal-> makeSoundAnyAnimal()
}
}
protected fun makeSoundDog() {
check(type == AnimalType.Dog)
println("woof")
}
protected fun makeSoundCat() {
check(type == AnimalType.Cat)
println("meow")
}
protected fun makeSoundAnyAnimal() {
println("---");
}
}
With inheritance this would look like this
open class Animal {
open fun makeSound() {}
}
class Dog : Animal {
override fun makeSound() {
println("woof")
}
}
class Cat : Animal {
override fun makeSound() {
println("meow")
}
}
When you write super.makeSound this would be like calling makeSoundAnyAnimal().
Note that when you call makeSound on a dog, inheritance or the override keyword does not just replace the Animal.makeSound function. It creates a new function. Whenever you call makeSound on any type of animal there is a system (called dynamic dispatch) which checks what type of animal you have and then calls the correct function. super.makeSound then calls the implementation of the parent class.
I didn’t understand quite. If doesn’t matter, why I don’t need to use override when defined an function (not open function only function). And I mean why I’m using super keyword rather I can call this function in another function from DoSomething class. It look like recursion. And as I said, I can call Func() function by another DoSomething function.
Um you seem confused and I can’t exactly understand what you’re saying.
So first of all usually when you override a function the overridden function does something different, it might call to the base implementation but doesn’t have to, see the examples from Wasabi.
So in the general case the base function and the overridden one are different. Now if you have a reference to Anything and call Func on it, that will call what the implementation of the actual class:
val anything: Anything = DoSomething()
anything.Func() // <-- this will call Func in DoSomething
Note that above anything is of type Anything, despite its concrte type being DoSomething.
If you have a reference to an object of type Anything there is no way for you call Anything’s implementation of Func.
In the case when you’re overriding a method you have a special syntax using super to call the base implementation method. If you just called Func() inside of Func() implementation in DoSomething that would be an infinite recursion.
I mean that the overriding function is indepdendent from the one in parent class. It does not change the function in the parent class. That one is still there and unchanged, but the child class now has it’s own function with the same name that is called instead of it.