avatarGabriel Shanahan

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

3069

Abstract

<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%2FnN9trogjq&amp;display_name=Kotlin+Playground&amp;url=https%3A%2F%2Fpl.kotl.in%2FnN9trogjq&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="cf3a">The issue here is almost identical — inside the <code>runOnA</code> block, we have <i>two</i> candidate values for <code>this</code> — the <code>block</code> is a function with receiver of type <code>A</code>, so an <code>A</code> instance is in scope inside the literal, but <code>block</code> is also defined as part of an extension function on <code>B</code>, which means that we have a <code>B</code> instance in scope as well.</p><h2 id="05ec">Qualified this</h2><p id="282f">This is identical to the situation encountered with <a href="https://readmedium.com/nested-and-inner-classes-b300243d036d">inner classes</a>, and the solution is also identical: <b>if not qualified, a <code>this</code> expression refers to the innermost enclosing scope</b>. If we want to refer to a different one, we need to qualify the <code>this</code> expression with a label by writing <code>this@label</code>.</p><p id="14b7">Implicit labels are created for every class body and function <b>statement</b> (not literal) body. Here is an example describing all the possibilities:</p> <figure id="03ce"> <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%2FjOKLGWp-s&amp;display_name=Kotlin+Playground&amp;url=https%3A%2F%2Fpl.kotl.in%2FjOKLGWp-s&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="78ac">This solves our problem when dealing with the receivers of statements (class and function definitions), but it still doesn’t help us with literals (anonymous functions &amp; lambdas with or without receivers). However, as was mentioned in the chapter on <a href="https://readmedium.com/nested-and-inner-classes-b300243d036d">inner classes</a>, (explicit) <b>labels can also be used to explicitly qualify expressions</b>. You can use that to your advantage when dealing with conflicting receivers inside literals:</p> <figure id="1fac"> <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%2FTrIoxmsbt&amp;display_name=Kotlin+P # Options layground&amp;url=https%3A%2F%2Fpl.kotl.in%2FTrIoxmsbt&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><h1 id="d1cb">Exercises</h1><p id="50db">It’s brain-fuck time! Spend some time thinking about what the <code>abc</code> function prints. Remember that <code>-&gt;</code> is right associative, so the type bellow is the same as <code>A.() -&gt; (B.() -&gt; (C.() -&gt; Unit))</code>.</p><p id="7cef">Start reading: "The function 'abc', when invoked, returns a function with receiver <code>A</code>, which, when invoked, returns a function...". Contrast this with the number of invocations in main.</p><p id="121f">Think about what this function prints when run in its current form. Run the example — were you right?</p> <figure id="37e3"> <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%2FMDyD-OHuF&amp;display_name=Kotlin+Playground&amp;url=https%3A%2F%2Fpl.kotl.in%2FMDyD-OHuF&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="890f">Make changes so it evaluates to <code>A B C</code>:</p> <figure id="29e8"> <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%2FBfF45HfYt%3Ffrom%3D20%26to%3D29&amp;display_name=Kotlin+Playground&amp;url=https%3A%2F%2Fpl.kotl.in%2FBfF45HfYt%3Ffrom%3D20%26to%3D29&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="a560">Go back to <a href="https://readmedium.com/functions-with-receiver-28b71b11ddde">Functions with Receiver</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/what-extension-functions-are-not-3c9fe874ed3a">What Extension Functions Are Not</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>

Qualified This

An interesting problem that arises when extensions are introduced, and how to solve it using labels and qualified this

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

THE CURRENT VERSION OF THIS ARTICLE IS PUBLISHED HERE.

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

Tags: #KOTLIN FEATURE #EXERCISE

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.

With the introduction of extension functions and functions with receiver, we open the doors to an interesting situation. Take a look at the following:

The problem with the above is that, in A.printX, there are actually two candidate values for this — an A instance is in scope because printX is an extension function on A, and a B instance is in scope because A.printX is also a method (i.e. defined inside B). While the example may seem synthetic, it is not all that uncommon for this to happen.

A slightly different but equivalent situation can arise with function literals with receiver:

The issue here is almost identical — inside the runOnA block, we have two candidate values for this — the block is a function with receiver of type A, so an A instance is in scope inside the literal, but block is also defined as part of an extension function on B, which means that we have a B instance in scope as well.

Qualified this

This is identical to the situation encountered with inner classes, and the solution is also identical: if not qualified, a this expression refers to the innermost enclosing scope. If we want to refer to a different one, we need to qualify the this expression with a label by writing this@label.

Implicit labels are created for every class body and function statement (not literal) body. Here is an example describing all the possibilities:

This solves our problem when dealing with the receivers of statements (class and function definitions), but it still doesn’t help us with literals (anonymous functions & lambdas with or without receivers). However, as was mentioned in the chapter on inner classes, (explicit) labels can also be used to explicitly qualify expressions. You can use that to your advantage when dealing with conflicting receivers inside literals:

Exercises

It’s brain-fuck time! Spend some time thinking about what the abc function prints. Remember that -> is right associative, so the type bellow is the same as A.() -> (B.() -> (C.() -> Unit)).

Start reading: "The function 'abc', when invoked, returns a function with receiver A, which, when invoked, returns a function...". Contrast this with the number of invocations in main.

Think about what this function prints when run in its current form. Run the example — were you right?

Make changes so it evaluates to A B C:

Go back to Functions with Receiver, jump to the Table of Contents, or continue to What Extension Functions Are Not.

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