Overridden functions of an open class is open by default and we can stop that by using the final Keyword

Meaning we can override and inherit overridden method by default.

Let’s say we built a learning app.

Course is our abstract class,

KotlinCourse inherits or extends Course,

SpecialKotlinCourse also inherits or extend KotlinCourse.

As you can see from the code below, SpecialKotlinCourse  is the grand child of Course and the child of KotlinCourse.

The method learn was overridden twice.

abstract class Course (val topic: String, var price : Double) {
    open fun learn(){
        println("Yay! am learning $topic")
    }
}

open class KotlinCourse : Course("Kotlin", 99.99){
    override fun learn() {
        println("Yay! I am one of the first to Learn Kotlin")
    }
}
class SpecialKotlinCourse : KotlinCourse() {
    override fun learn() {
        super.learn()
    }
}

let’s say we have many open methods in Course (abstract class), would grand children, great grand children, … of Course need to override all of the methods all the time? NO

you can stop this ‘overriding madness’ by simply introducing the final keyword at any level of inheritance to stop it from being overrode in the child class.

abstract class Course(val topic: String, var price: Double) {
    open fun learn() {
        println("Yay! am learning $topic")
    }

    open fun secondMethod() {
        println("Second Method")
    }
}
open class KotlinCourse : Course("Kotlin", 99.99) {
    override final fun learn() {
        println("Yay! I am one of the first to Learn Kotlin")
    }

    override fun secondMethod() {
        println("KotlinCourse - Second Method")
    }
}

open class SpecialKotlinCourse : KotlinCourse() {
    override final fun secondMethod() {
        super.secondMethod()
    }
}

class VerySpecialKotlinCourse : SpecialKotlinCourse() {
    //Code will not compile because it has 
// been declared 'final' in super class 'SpecialKotlinCourse'
    override fun secondMethod() {
        super.secondMethod()
    }

    //Code will not compile because it has 
    // been declared 'final' in super class 'SpecialKotlinCourse'
    override final fun learn() {
        println("Yay! I am one of the first to Learn Kotlin")
    }
}

Inheriting Functions of the Same Name

when we inherit a class (or an interface) which has one or more functions with the same name, we might have an issue using the super keyword, as it will not know which of the class you are referencing (ambiguity).

[box type=”info” align=”” class=”” width=””]

super keyword refers to our super class

If we override a method nameofMethodsuper.nameOfMethod() will execute the default code defined in nameofMethod

[/box]

using

super<Insert Name of extended Class (or implemented Interface)>.nameOfMethod()

we can define which super class method to execute

interface Learnable{
    fun learn(){
       println("I am Learning...") 
    }
}

abstract class Course(val topic: String, var price: Double) {
    open fun learn() {
        println("Yay! am learning a great $topic course!")
    }
}

open class KotlinCourse : Course("Kotlin", 99.99), Learnable {
    override final fun learn() {
        super<Course>.learn() // 'Yay! am learning a great Kotlin course!'
        println("I am one of the first to learn Kotlin")
    }
}
open class KotlinCourseONE : Course("Kotlin", 99.99), Learnable {
    override final fun learn() {
        super<Learnable>.learn() // 'I am Learning...'
        println("I am one of the first to learn Kotlin")
    }
}
class Example {
    fun main (args : Array){
        val kc : KotlinCourse = KotlinCourse()
        kc.learn()
        // Yay! am learning a great Kotlin course!
        // I am one of the first to learn Kotlin

        val kc1: KotlinCourseONE = KotlinCourseONE()
        kc1.learn()
        // I am Learning...
        // I am one of the first to learn Kotlin
    }
}

doing the above can let us specify which of the similar function,from different class (or interface) we want to execute.

if you remove the super<…> both the compiler will not be able to differentiate between which similar of the different classes (or interface) you may want to execute. Hence both are implemented as one.

interface Learnable{
    fun learn(){
       println("I am Learning...")
    }
}

abstract class Course(val topic: String, var price: Double) {
    open fun learn() {
        println("Yay! am learning a great $topic course!")
    }
}

open class KotlinCourse : Course("Kotlin", 99.99), Learnable {
    override final fun learn() {
        println("I am one of the first to learn Kotlin")
    }
}

class Example {
 fun main (args : Array<String>){
 val kc : KotlinCourse = KotlinCourse()
 kc.learn()
 // I am one of the first to learn Kotlin
 }
}

Leave a comment