thing</i>, the “main” parameter (called a <b>receiver</b>) from the others, and define a very special way it is passed to the method (<code><importantParameter>.<method>(<otherParameters>)</code>) and accessed inside it (<code>this</code>)</li><li>they live in the same file, between the <code>{</code> and <code>}</code> defining the class body</li></ul><p id="d171">Modeling solutions as a set of <i>things</i> (classes) that have <i>behaviors </i>(methods) is a very useful way of structuring our code, because it reflects the way we naturally think about the world. This is, of course, a core motivation for OOP.</p><p id="b8fc">However, the Java class model limits the way methods can be defined:</p><ul><li>A behavior (method) can only belong to a single class</li><li>All methods which are part of a class must be specified when that class is defined. There is no way to add a method to a class without modifying its definition</li></ul><p id="8082">This is problematic for one crucial reason: <b>most behaviors are not actually part of the core essence of a class, but are only relevant in certain contexts. Additionally, some behaviors belong equally to two (or more) classes</b>.</p><h1 id="816c">Example</h1><p id="c371">Imagine we are writing an IDE for databases. First, we created the core engine, and in the process created a <code>DatabaseTable</code> class:</p>
<figure id="657d">
<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%2FEgCFqjpBS&display_name=Kotlin+Playground&url=https%3A%2F%2Fpl.kotl.in%2FEgCFqjpBS&image=https%3A%2F%2Fplay.kotlinlang.org%2Fassets%2Fog-image.png&key=a19fcc184b9711e1b4764040d3dc5c07&type=text%2Fhtml&schema=kotl" allowfullscreen="" frameborder="0" height="300" width="800">
</div>
</div>
</figure></iframe></div></div></figure><p id="200e">Next, we are tasked with writing the GUI module, which renders a visual representation of a <code>DatabaseTable</code> to the screen. It is clear that a <code>renderTo(buffer: FrameBuffer)</code> function is strongly related to a <code>DatabaseTable</code> and could easily be considered its behavior in the context of a GUI application - things are able to render themselves.</p><p id="5e42">At the same time, we might feel some trepidation at the thought of adding the <code>renderTo</code> function to the <code>DatabaseTable</code> class, because it's not actually tied to the <b>core essence</b> of a <code>DatabaseTable</code>. If we were writing a general database library, we most certainly would not include a <code>renderTo</code> function in the <code>DatabaseTable</code> class, would we? The <code>renderTo</code> function exists as a behavior of a <code>DatabaseTable</code> only in the context of a GUI application. In fact, we could go one step further and say it's only relevant in the context of the <code>GUI</code> <i>module</i> - that's the only place we actually talk about rendering. Anywhere else, e.g. in a module that deals with persisting a <code>DatabaseTable</code> to disk, rendering is an alien concept that has no meaning.</p><figure id="33a5"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/0*RCc7Fuxvg9Wq6ilq.png"><figcaption>Structuring your code is important</figcaption></figure><p id="f000">Unfortunately, due to the limitations mentioned above, we only have two choices:</p><h2 id="15a1">Defining the renderTo function outside the class</h2><p id="8436">This has the benefit of allowing us to specify that rendering is a domain in its own right (e.g. by creating a <code>Renderer</code> class).</p><p id="5952">Unfortunately, it also forces us to write less elegant code when actually using the function, and makes the whole solution more complex by introducing a new concept (a thing that renders), which would not strictly be necessary otherwise.</p><p id="ff12">Another problem is that we have no easy way of writing code that works for “anything that is ‘renderable’” — normally, we would define a <code>Renderable</code> interface, but that would require defining the <code>renderTo</code> function on the class. Solving this problem is not necessarily impossible, but at
Options
the very least becomes more complex.</p><p id="2917">Solving this problem is not necessarily impossible, but at the very least becomes more complex.</p><h2 id="c409">Defining the renderTo function inside the class</h2><p id="9f08">In the long term, this approach leads to bloated classes that are extremely cluttered and difficult to understand. This is because we understand things <i>through the way they behave</i> (what they do), but in this approach, each class contains lots of behavior that has nothing to do with what it actually <i>is</i> at its core. In a sense, we again lose the ability to communicate to a future reader what we were thinking. We also lose the ability to communicate that rendering in fact also belongs to a domain of its own.</p><p id="bcd9">The situation is even worse when we aren’t the authors of the class in question (i.e. <code>DatabaseTable</code> is part of a third-party library). In this case, we are completely limited to the API defined in the library and only have the option of defining additional methods outside the class. Since the vast majority of classes we work with are part of external libraries, this is the case that happens most often.</p><h2 id="aa6d">Defining Methods Outside of Classes</h2><p id="45ae">A lot of these problems would be easier to avoid if we could somehow <b>define methods which belong to a class, but are defined outside of classes</b>. If we could say “this behavior belongs to that class”, but say so in a different file, we would be able to:</p><ul><li>preserve the special syntax (receivers and <code>this</code>) provided by methods</li><li>emphasize that a behavior “belongs” to a certain thing</li><li>emphasize that a behavior is only relevant in a certain context (i.e. it would <b>not</b> be defined as part of the class body, but instead live somewhere else — a top-level definition in another file, or perhaps as a part of another class)</li><li>keep the core behavior of classes slimmed down to what is actually part of their essence, making them easier to understand (only the core things are defined as methods inside the body)</li></ul><p id="29ac">Extension methods provide a way to do precisely this:</p>
<figure id="8933">
<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%2Fu0INX9IpW&display_name=Kotlin+Playground&url=https%3A%2F%2Fpl.kotl.in%2Fu0INX9IpW&image=https%3A%2F%2Fplay.kotlinlang.org%2Fassets%2Fog-image.png&key=a19fcc184b9711e1b4764040d3dc5c07&type=text%2Fhtml&schema=kotl" allowfullscreen="" frameborder="0" height="300" width="800">
</div>
</div>
</figure></iframe></div></div></figure><p id="7899">At the beginning of this article, we asked <i>what kind of information becomes easier to communicate with extension functions</i>.</p><p id="4b1f">The answer, as we have seen, is:</p><ul><li>it is easier to communicate what constitutes the essence of a class, and what is just additional behavior relevant only to certain contexts/domains, because we can separate the two (through syntax and through different locations of the definitions). In turn, it is easier to understand what classes <i>are</i>, because they are slimmer and contain less behavior for the reader to absorb</li><li>it is easier to group behaviors of classes by the contexts/domains they are relevant to, because they needn’t be defined in the same location as the class. This makes it easier to structure our projects.</li></ul><p id="c99c">Go back to <a href="https://readmedium.com/functional-sam-interfaces-b25018e9064f">Functional (SAM) Interfaces</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/extension-functions-syntax-and-behavior-e56ba07548f">Syntax and Behavior</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&utm_medium=GabrielShanahan&utm_campaign=KotlinPrimer&utm_content=join-our-team&utm_term=KotlinPrimer#pozice">Join me in Etnetera</a></figcaption></figure></article></body>
Extension Functions: Motivation
An introduction to the problems that extension functions solve, why code isn’t written for computers anymore, and what that means for how we write code
— — — — — — — — — — — — — — —
THE CURRENT VERSION OF THIS ARTICLE IS PUBLISHED HERE.
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.
Extension functions are probably among the features of Kotlin which can be a little more difficult to grasp, for one simple reason — they don’t actually make writing any kind of code that much easier, apart from a small amount of sugar coating. They add form, not function. Because of this, it is often not clear when they should be used or why, and if you Google “Kotlin when to use extension functions”, you will find hundreds of articles addressing this very issue.
There is nothing inherently complicated about the mechanics of extension functions and their syntax can be explained quickly and easily. What really requires discussion is the ‘why’ and ‘how’, which is what I will spend most of these articles talking about.
Importance of Maintainability
A well understood but key fact one needs to accept before understanding the benefits of extension functions is this: most code is not written primarily for computers anymore. Code is written for other humans to read, understand, debug, refactor, improve, etc. On a long enough time scale, maintenance outgrows all other costs.
On a long enough time scale, maintenance outgrows all other costs
Because of this, our goals when writing code must be different from what they used to be. It is no longer just about writing code that works, but also about writing code that is clear, structured, readable and self-documenting — all things which make maintenance easier. These traits are often valued above all else, including above code which is more optimized, especially under the assumptions discussed in the preface.
One of the things we do to achieve this is to structure our code in a way that communicates how we are thinking. And when viewed from this perspective, the question regarding extension functions becomes not only what functionality becomes easier to implement with extension functions but also what information becomes easier to communicate to the reader with extension functions.
Limitations of Java
One of the main things we communicate through our code structure is the relationship between things (classes) and behaviors (methods). Java methods have special syntax rules that are able to communicate that a behavior belongs to a certain thing:
they separate the thing, the “main” parameter (called a receiver) from the others, and define a very special way it is passed to the method (<importantParameter>.<method>(<otherParameters>)) and accessed inside it (this)
they live in the same file, between the { and } defining the class body
Modeling solutions as a set of things (classes) that have behaviors (methods) is a very useful way of structuring our code, because it reflects the way we naturally think about the world. This is, of course, a core motivation for OOP.
However, the Java class model limits the way methods can be defined:
A behavior (method) can only belong to a single class
All methods which are part of a class must be specified when that class is defined. There is no way to add a method to a class without modifying its definition
This is problematic for one crucial reason: most behaviors are not actually part of the core essence of a class, but are only relevant in certain contexts. Additionally, some behaviors belong equally to two (or more) classes.
Example
Imagine we are writing an IDE for databases. First, we created the core engine, and in the process created a DatabaseTable class:
Next, we are tasked with writing the GUI module, which renders a visual representation of a DatabaseTable to the screen. It is clear that a renderTo(buffer: FrameBuffer) function is strongly related to a DatabaseTable and could easily be considered its behavior in the context of a GUI application - things are able to render themselves.
At the same time, we might feel some trepidation at the thought of adding the renderTo function to the DatabaseTable class, because it's not actually tied to the core essence of a DatabaseTable. If we were writing a general database library, we most certainly would not include a renderTo function in the DatabaseTable class, would we? The renderTo function exists as a behavior of a DatabaseTable only in the context of a GUI application. In fact, we could go one step further and say it's only relevant in the context of the GUImodule - that's the only place we actually talk about rendering. Anywhere else, e.g. in a module that deals with persisting a DatabaseTable to disk, rendering is an alien concept that has no meaning.
Structuring your code is important
Unfortunately, due to the limitations mentioned above, we only have two choices:
Defining the renderTo function outside the class
This has the benefit of allowing us to specify that rendering is a domain in its own right (e.g. by creating a Renderer class).
Unfortunately, it also forces us to write less elegant code when actually using the function, and makes the whole solution more complex by introducing a new concept (a thing that renders), which would not strictly be necessary otherwise.
Another problem is that we have no easy way of writing code that works for “anything that is ‘renderable’” — normally, we would define a Renderable interface, but that would require defining the renderTo function on the class. Solving this problem is not necessarily impossible, but at the very least becomes more complex.
Solving this problem is not necessarily impossible, but at the very least becomes more complex.
Defining the renderTo function inside the class
In the long term, this approach leads to bloated classes that are extremely cluttered and difficult to understand. This is because we understand things through the way they behave (what they do), but in this approach, each class contains lots of behavior that has nothing to do with what it actually is at its core. In a sense, we again lose the ability to communicate to a future reader what we were thinking. We also lose the ability to communicate that rendering in fact also belongs to a domain of its own.
The situation is even worse when we aren’t the authors of the class in question (i.e. DatabaseTable is part of a third-party library). In this case, we are completely limited to the API defined in the library and only have the option of defining additional methods outside the class. Since the vast majority of classes we work with are part of external libraries, this is the case that happens most often.
Defining Methods Outside of Classes
A lot of these problems would be easier to avoid if we could somehow define methods which belong to a class, but are defined outside of classes. If we could say “this behavior belongs to that class”, but say so in a different file, we would be able to:
preserve the special syntax (receivers and this) provided by methods
emphasize that a behavior “belongs” to a certain thing
emphasize that a behavior is only relevant in a certain context (i.e. it would not be defined as part of the class body, but instead live somewhere else — a top-level definition in another file, or perhaps as a part of another class)
keep the core behavior of classes slimmed down to what is actually part of their essence, making them easier to understand (only the core things are defined as methods inside the body)
Extension methods provide a way to do precisely this:
At the beginning of this article, we asked what kind of information becomes easier to communicate with extension functions.
The answer, as we have seen, is:
it is easier to communicate what constitutes the essence of a class, and what is just additional behavior relevant only to certain contexts/domains, because we can separate the two (through syntax and through different locations of the definitions). In turn, it is easier to understand what classes are, because they are slimmer and contain less behavior for the reader to absorb
it is easier to group behaviors of classes by the contexts/domains they are relevant to, because they needn’t be defined in the same location as the class. This makes it easier to structure our projects.