avatarGabriel Shanahan

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

3520

Abstract

frameborder="0" height="300" width="800"> </div> </div> </figure></iframe></div></div></figure><p id="01ef">In both cases, there are limitations to the way extension can be defined and used, but before we get to them, we’ll talk about what extensions actually are under the hood — this will lead to a very clear understanding of what the limitations are and why that is the case.</p><h2 id="da74">Under the Hood</h2><p id="6266">Extension functions are actually nothing more than regular functions with a “hidden” first argument representing the receiver.</p> <figure id="b0d2"> <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%2FRRblFl48O&amp;display_name=Kotlin+Playground&amp;url=https%3A%2F%2Fpl.kotl.in%2FRRblFl48O&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="6138">That’s it, really.</p><p id="1a9c">In fact, if you actually tried to define both of the above functions with the same name, you would get an error similar to <code>Platform declaration clash: The declarations have the same JVM signature</code>.</p><h2 id="41f1">Consequences</h2><p id="9e20">It is really important to fully understand what we just said: <b>extensions are just regular functions + syntactic sugar which hides a parameter and exposes it through <code>this</code></b>. Extensions don't modify classes and are in no way part of the class. Anything you can write with an extension, you can also write using a regular function which accepts the receiver as an explicit parameter:</p> <figure id="26bc"> <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%2FvlG6TaqNK&amp;display_name=Kotlin+Playground&amp;url=https%3A%2F%2Fpl.kotl.in%2FvlG6TaqNK&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="b363">Both do the same thing. No magic involved.</p><p id="2655">Let us explicitly list some consequences of the above:</p><ul><li><b>Extensions cannot access private and protected members of the classes they extend</b></li></ul><p id="09cb">Not having this limitation would cause a lot of problems because it would break encapsulation, but it also makes complete sense since extensions are nothing more than regular functions.</p><ul><li><b>Extension functions can have visibility modifiers, but they work in the same way as with top-level functions</b></li></ul> <figure id="9911"> <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%2FtsDbZkp9o&amp;display_name=Kotlin+Playground&amp;url=https%3A%2F%2Fpl.kotl.in%2FtsDbZkp9o&amp;image=https%3A%2F%2Fplay.kotlinlang.org%2Fassets%2F

Options

og-image.png&key=a19fcc184b9711e1b4764040d3dc5c07&type=text%2Fhtml&schema=kotl" allowfullscreen="" frameborder="0" height="300" width="800"> </div> </div> </figure></iframe></div></div></figure><ul><li><b>Extension properties can only be synthetic</b></li></ul><p id="a7fc">Since extensions cannot actually modify classes, there is no way they could add a backing field to it. Another way to put it is that extensions are only functions, and functions can’t have backing fields associated with them.</p> <figure id="2d33"> <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%2FXb0MZBIpl&amp;display_name=Kotlin+Playground&amp;url=https%3A%2F%2Fpl.kotl.in%2FXb0MZBIpl&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><ul><li><b>Extensions are dispatched statically</b></li></ul> <figure id="f7c9"> <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%2FC_Bm986-4&amp;display_name=Kotlin+Playground&amp;url=https%3A%2F%2Fpl.kotl.in%2FC_Bm986-4&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="0831">This makes perfect sense when seeing extensions for what they really are — regular functions with the receiver as the first argument. We are not <a href="https://www.educative.io/answers/overloading-vs-overriding"><i>overriding</i> the function, but <i>overloading</i> it</a>.</p> <figure id="9edb"> <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%2FhxyFn-3Kd&amp;display_name=Kotlin+Playground&amp;url=https%3A%2F%2Fpl.kotl.in%2FhxyFn-3Kd&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="c99c">Go back to <a href="https://readmedium.com/extension-functions-motivation-a55abc644c5a">Extension Functions: Motivation</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/functions-with-receiver-28b71b11ddde">Functions with Receiver</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>

Extension Functions: Syntax and Behavior

Extension functions & properties, what they are under the hood, and the consequences for encapsulation, visibility modifiers, the way they are dispatched, and more

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

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.

Types of Extensions

There are actually two types of extensions in Kotlin — extension functions and extension properties.

As seen in the previous article, extension functions are defined in the same way as regular functions, with the receiver prepended to the function name:

They are most often defined as top-level functions which can be imported in the same way as regular functions are, e.g. import a.b.c.repeatTwice for the example above. You can also define extension functions inside classes, which we will discuss more in a future article.

Things are very similar with extension properties:

In both cases, there are limitations to the way extension can be defined and used, but before we get to them, we’ll talk about what extensions actually are under the hood — this will lead to a very clear understanding of what the limitations are and why that is the case.

Under the Hood

Extension functions are actually nothing more than regular functions with a “hidden” first argument representing the receiver.

That’s it, really.

In fact, if you actually tried to define both of the above functions with the same name, you would get an error similar to Platform declaration clash: The declarations have the same JVM signature.

Consequences

It is really important to fully understand what we just said: extensions are just regular functions + syntactic sugar which hides a parameter and exposes it through this. Extensions don't modify classes and are in no way part of the class. Anything you can write with an extension, you can also write using a regular function which accepts the receiver as an explicit parameter:

Both do the same thing. No magic involved.

Let us explicitly list some consequences of the above:

  • Extensions cannot access private and protected members of the classes they extend

Not having this limitation would cause a lot of problems because it would break encapsulation, but it also makes complete sense since extensions are nothing more than regular functions.

  • Extension functions can have visibility modifiers, but they work in the same way as with top-level functions
  • Extension properties can only be synthetic

Since extensions cannot actually modify classes, there is no way they could add a backing field to it. Another way to put it is that extensions are only functions, and functions can’t have backing fields associated with them.

  • Extensions are dispatched statically

This makes perfect sense when seeing extensions for what they really are — regular functions with the receiver as the first argument. We are not overriding the function, but overloading it.

Go back to Extension Functions: Motivation, jump to the Table of Contents, or continue to Functions with Receiver.

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