2. Dispatch receiver - A function member of the class calls one of its member. A member invoking another member of the same class.

3. Extension receiver - You call the function member of the class your extending inside that class function extension. An extension function invoking a member of the class your extending.

note: In case of conflict with dispatch and extension receiver, the extension receiver has high precedence since it was an extension function after all. If you want to use the dispatch receiver, use the this keyword followed by at sign with class name and a dot and then, the function member. Assuming this /../ is an at sign.

this/../String.hello("")

In case of conflict in the overridden extension function, it always follows the class type of the invocation.

===================

fun main(){

    val tf = TrafficEnforcer("Why are you here?", "To mingle")

    tf.displayWithMother(Mother())

    tf.displayWithChild(Child())

}

open class Mother{

    fun sayMother(){

        print("Mother based --- ")

    }

}

class Child: Mother(){

    fun sayChild(){

        print("Child based --- ")

    }

}

open class Enforcer{

     open fun Mother.displaySomething(message: String){

         sayMother()

         forTheSakeOfDispatch()

         println(message)

     }

     open fun Child.displaySomething(message: String){

         sayChild()

         println(message) 

     }

     fun forTheSakeOfDispatch(){

         println("I am the Enforcer")

     }

}

class TrafficEnforcer(private val motherMessage: String, private val childMessage: String) : Enforcer(){

    override fun Mother.displaySomething(message: String){

        println("Traffic from Mother: $message")

    }

    override fun Child.displaySomething(message: String){

        println("Traffic form Child: $message")

    }

    fun displayWithMother(mother: Mother){

        mother.sayMother()

        mother.displaySomething(motherMessage)

    }

    fun displayWithChild(child: Child){

       child.sayChild()

       child.displaySomething(childMessage)

    }

}

===================

Result:

Mother based --- Traffic from Mother: Why are you here?

Child based --- Traffic from Child: To mingle


Note:

1. In the extension below, the sayMother() method invocation is the extension receiver. The implicit object receiver is the Mother. The forTheSakeOfDispatch() method invocation is the dispatch receiver. The implicit object of dispatch receiver is the Enforcer.

open fun Mother.displaySomething(message: String){

     sayMother()

     forTheSakeOfDispatch()

     println(message)

}

2. The type in the parameter of the function displayWithMother() is the Mother. So, it displays the override mother extension.

 fun displayWithMother(mother: Mother){

     mother.sayMother()

     mother.displaySomething(motherMessage)

}

3. In main, we used the trafficEnforcer object. So, everything was get from the Traffic Enforcer class. But if you want to test, you can create another displayWithMother() method in Enforcer. Be sure not to be overshadowed by the TrafficEnforcer. Just change the name a little bit. Then, in the main, you create an Enforcer object and access the displayWithMother() method. In this way, everything will be taken from the Enforcer class.

Therefore based on the example, in the case of overridden example conflict, the function that will run depends on the object that implements and the object parameter that was called in the function.

Kotlin ProgrammingWhere stories live. Discover now