avatarGabriel Shanahan

Free AI web copilot to create summaries, insights and extended knowledge, download it at here

2640

Abstract

92d20ac2">type class</a>.</p><p id="1df6">There was <a href="https://github.com/Kotlin/KEEP/pull/87">a long discussion</a> about if and how to add similar capability to Kotlin, with the result being a shift towards <a href="https://youtrack.jetbrains.com/issue/KT-10468">extension functions with multiple receivers</a>. This has now been implemented as <a href="https://github.com/Kotlin/KEEP/blob/master/proposals/context-receivers.md">context receivers</a>, and I’ll talk about those in a different article.</p><p id="f23d">However, you’re not without options:</p><p id="33e7"><b>You can use delegates</b></p> <figure id="4e57"> <div> <div> <img class="ratio" src="http://placehold.it/16x9"> <iframe class="" src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fpl.kotl.in%2FXIY7pbnMy&amp;display_name=Kotlin+Playground&amp;url=https%3A%2F%2Fpl.kotl.in%2FXIY7pbnMy&amp;image=https%3A%2F%2Fplay.kotlinlang.org%2Fassets%2Fog-image.png&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=kotl" allowfullscreen="" frameborder="0" height="300" width="800"> </div> </div> </figure></iframe></div></div></figure><p id="6a1e"><b>You can implement the interface contract using extension functions and pass an anonymous object “delegating” to those extension functions</b></p> <figure id="5f12"> <div> <div> <img class="ratio" src="http://placehold.it/16x9"> <iframe class="" src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fpl.kotl.in%2FxZGjKh0GM&amp;display_name=Kotlin+Playground&amp;url=https%3A%2F%2Fpl.kotl.in%2FxZGjKh0GM&amp;image=https%3A%2F%2Fplay.kotlinlang.org%2Fassets%2Fog-image.png&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=kotl" allowfullscreen="" frameborder="0" height="300" width="800"> </div> </div> </figure></iframe></div></div></figure><h2 id="7753">Methods Belonging To Multiple Classes</h2><p id="22d7">At first glance, it might seem that you can, in fact, use extension functions to create a method belonging to more than once class.</p> <figure id="a819"> <div> <div> <img class="ratio" src="http://placehold.it/16x9"> <iframe class="" src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fpl.kotl.in%2FrpQRDNTPg&amp;display_name=Kotlin+Playground&amp;url=https%3A%2F%2Fpl.kotl.in%2FrpQRDNTPg&amp;image=https%3A%2F%2Fplay.kotlinlang.org%2Fassets%2Fog-image.png&am

Options

p;key=a19fcc184b9711e1b4764040d3dc5c07&type=text%2Fhtml&schema=kotl" allowfullscreen="" frameborder="0" height="300" width="800"> </div> </div> </figure></iframe></div></div></figure><p id="e2fa">In a way, the method above “belongs” to 2 classes at once, in the sense that there are two <code>this</code> values available and the method can only be called when both an <code>A</code> and <code>B</code> instance is in scope. However, there are two crucial differences:</p><ol><li><a href="https://readmedium.com/static-and-dynamic-dispatch-324d3dc890a3">method receivers are dynamically dispatched, while extension function receivers are statically dispatched</a>. In other words, the implementation to call is chosen by the <b>runtime type</b> of the receiver in the case of methods, but by the <b>compile-time type</b> of the receiver in the case of extension functions</li><li>methods can use protected and private methods of the class it is defined on. Extensions can’t, because that would break encapsulation</li></ol><p id="57b1">The solution to the first problem is called <a href="https://jj.hashnode.dev/learn-the-true-polymorphism">multiple dispatch</a>, and it is supported by some languages. Methods that take advantage of multiple dispatch are called “multi-methods”. Equivalent behavior <a href="https://en.wikipedia.org/wiki/Multiple_dispatch#Java">can be emulated</a> in Java/Kotlin, although it is a little unwieldy.</p><p id="5a5e">The second issue is usually not solvable even in languages which support multiple dispatch — in those languages, multi-methods are considered “outside” of all the classes. Indeed, languages with multiple dispatch often have no concept of encapsulation in the first place. For those interested, one of the few exceptions to this rule is <a href="http://laputan.org/pub/papers/cecil-ecoop-92.pdf">Cecil</a>.</p><p id="c1af">Go back to <a href="https://readmedium.com/qualified-this-578e7809d8f6">Qualified This</a>, jump to the <a href="https://readmedium.com/table-of-contents-c52573cfa291">Table of Contents</a>, or continue to <a href="https://readmedium.com/nullable-generic-receivers-3d01f435bb73">Extension Function Applications: Nullable & Generic Receivers</a>.</p><figure id="8ecd"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*biBSB579iezsNvEQ_NMLBg.png"><figcaption><a href="https://www.etnetera.cz/prace-u-nas?utm_source=medium&amp;utm_medium=GabrielShanahan&amp;utm_campaign=KotlinPrimer&amp;utm_content=join-our-team&amp;utm_term=KotlinPrimer#pozice">Join me in Etnetera</a></figcaption></figure></article></body>

What Extension Functions Are Not

External implementations of interfaces, multi-methods, and what you can do instead

— — — — — — — — — — — — — — —

THE CURRENT VERSION OF THIS ARTICLE IS PUBLISHED HERE.

— — — — — — — — — — — — — — —

Tags: #FUNDAMENTAL CONCEPT

This article is part of the Kotlin Primer, an opinionated guide to the Kotlin language, which is indented to help facilitate Kotlin adoption inside Java-centric organizations. It was originally written as an organizational learning resource for Etnetera a.s. and I would like to express my sincere gratitude for their support.

It is recommended to read the Introduction before moving on. Check out the Table of Contents for all articles.

We’ve spent the previous few articles talking about what extension functions are, but it’s also important to understand what they are not. So let’s take a look at a couple of things that cannot be achieved using extension functions.

Implementing Interfaces Outside of a Class Definition

When discussing the motivation for extension functions, we mentioned the problem of not being able to have a DatabaseTable implement a Renderable interface when defining the renderTo function outside the class. Extension functions do not and cannot solve this problem.

Being able to have classes implement interfaces without changing their definition is something not usually supported in the C family of languages, with the exception of Swift and Scala. The technical term for the thing that would allow us to do this is a type class.

There was a long discussion about if and how to add similar capability to Kotlin, with the result being a shift towards extension functions with multiple receivers. This has now been implemented as context receivers, and I’ll talk about those in a different article.

However, you’re not without options:

You can use delegates

You can implement the interface contract using extension functions and pass an anonymous object “delegating” to those extension functions

Methods Belonging To Multiple Classes

At first glance, it might seem that you can, in fact, use extension functions to create a method belonging to more than once class.

In a way, the method above “belongs” to 2 classes at once, in the sense that there are two this values available and the method can only be called when both an A and B instance is in scope. However, there are two crucial differences:

  1. method receivers are dynamically dispatched, while extension function receivers are statically dispatched. In other words, the implementation to call is chosen by the runtime type of the receiver in the case of methods, but by the compile-time type of the receiver in the case of extension functions
  2. methods can use protected and private methods of the class it is defined on. Extensions can’t, because that would break encapsulation

The solution to the first problem is called multiple dispatch, and it is supported by some languages. Methods that take advantage of multiple dispatch are called “multi-methods”. Equivalent behavior can be emulated in Java/Kotlin, although it is a little unwieldy.

The second issue is usually not solvable even in languages which support multiple dispatch — in those languages, multi-methods are considered “outside” of all the classes. Indeed, languages with multiple dispatch often have no concept of encapsulation in the first place. For those interested, one of the few exceptions to this rule is Cecil.

Go back to Qualified This, jump to the Table of Contents, or continue to Extension Function Applications: Nullable & Generic Receivers.

Join me in Etnetera
Java
Kotlin
Programming
Object Oriented
Functional Programming
Recommended from ReadMedium