Skip to content

Commit bd63334

Browse files
committed
feat: add Kotlin intermediate tour extension functions
1 parent b216ee3 commit bd63334

File tree

5 files changed

+192
-5
lines changed

5 files changed

+192
-5
lines changed
59.6 KB
Loading

docs/kr.tree

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
<toc-element hidden="true" topic="kotlin-tour-functions.md"/>
1212
<toc-element hidden="true" topic="kotlin-tour-classes.md"/>
1313
<toc-element hidden="true" topic="kotlin-tour-null-safety.md"/>
14+
<toc-element hidden="true" topic="kotlin-tour-intermediate-extension-functions.md"/>
1415
</toc-element>
1516
<toc-element toc-title="Kotlin overview">
1617
<toc-element topic="multiplatform.topic"/>

docs/topics/tour/kotlin-tour-collections.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,8 +96,8 @@ fun main() {
9696
> functions are examples of **extension** functions. To call an extension function on an object, write the function name
9797
> after the object appended with a period `.`
9898
>
99-
> For more information about extension functions, see [Extension functions](extensions.md#extension-functions).
100-
> For the purposes of this tour, you only need to know how to call them.
99+
> Extension functions are covered in detail [in the intermediate tour](kotlin-tour-intermediate-extension-functions.md#extension-functions).
100+
> For now, you only need to know how to call them.
101101
>
102102
{style="note"}
103103

Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
[//]: # (title: Intermediate: Extension functions)
2+
3+
<tldr>
4+
<p><img src="icon-1.svg" width="20" alt="First step" /> <strong>Extension functions</strong><br />
5+
<img src="icon-2-todo.svg" width="20" alt="Second step" /> <a href="kotlin-tour-intermediate-scope-functions.md">Scope functions</a><br />
6+
<img src="icon-3-todo.svg" width="20" alt="Third step" /> <a href="kotlin-tour-intermediate-lambdas-receiver.md">Lambda expressions with receiver</a><br />
7+
<img src="icon-4-todo.svg" width="20" alt="Fourth step" /> <a href="kotlin-tour-intermediate-classes-interfaces.md">Classes and interfaces</a><br />
8+
<img src="icon-5-todo.svg" width="20" alt="Fifth step" /> <a href="kotlin-tour-intermediate-objects.md">Objects</a><br />
9+
<img src="icon-6-todo.svg" width="20" alt="Sixth step" /> <a href="kotlin-tour-intermediate-open-special-classes.md">Open and special classes</a><br />
10+
<img src="icon-7-todo.svg" width="20" alt="Seventh step" /> <a href="kotlin-tour-intermediate-properties.md">Properties</a><br />
11+
<img src="icon-8-todo.svg" width="20" alt="Eighth step" /> <a href="kotlin-tour-intermediate-null-safety.md">Null safety</a><br />
12+
<img src="icon-9-todo.svg" width="20" alt="Ninth step" /> <a href="kotlin-tour-intermediate-libraries-and-apis.md">Libraries and APIs</a></p>
13+
</tldr>
14+
15+
In this chapter, you'll explore special Kotlin functions that make your code more concise and readable. Learn how they
16+
can help you use efficient design patterns to take your projects to the next level.
17+
18+
## Extension functions
19+
20+
In software development, you often need to modify the behavior of a program without altering the original source code.
21+
For example, in your project, you might want to add extra functionality to a class from a third-party library.
22+
23+
Extension functions allow you to extend a class with additional functionality. You call extension functions the same way
24+
you call member functions of a class.
25+
26+
Before introducing the syntax for extension functions, you need to understand the terms **receiver type** and
27+
**receiver object**.
28+
29+
The receiver object is what the function is called on. In other words, the receiver is where or with whom the information is shared.
30+
31+
![An example of sender and receiver](receiver-highlight.png){width="500"}
32+
33+
In this example, the `main()` function calls the [`.first()`](https://kotlinlang.org/api/core/kotlin-stdlib/kotlin.collections/first.html) function.
34+
The `.first()` function is called **on** the `readOnlyShapes` variable, so the `readOnlyShapes` variable is the receiver.
35+
36+
The receiver object has a **type** so that the compiler understands when the function can be used.
37+
38+
This example uses the `.first()` function from the standard library to return the first element in a list. To create
39+
your own extension function, write the name of the class that you want to extend followed by a `.` and the name of
40+
your function. Continue with the rest of the function declaration, including its arguments and return type.
41+
42+
For example:
43+
44+
```kotlin
45+
fun String.bold(): String = "<b>$this</b>"
46+
47+
fun main() {
48+
// "hello" is the receiver object
49+
println("hello".bold())
50+
// <b>hello</b>
51+
}
52+
```
53+
{kotlin-runnable="true" kotlin-min-compiler-version="1.3" id="kotlin-tour-extension-function"}
54+
55+
In this example:
56+
57+
* `String` is the extended class, also known as the receiver type.
58+
* `bold` is the name of the extension function.
59+
* The `.bold()` extension function's return type is `String`.
60+
* `"hello"`, an instance of `String`, is the receiver object.
61+
* The receiver object is accessed inside the body by the [keyword](keyword-reference.md): `this`.
62+
* A string template (`$`) is used to access the value of `this`.
63+
* The `.bold()` extension function takes a string and returns it in a `<b>` HTML element for bold text.
64+
65+
## Extension-oriented design
66+
67+
You can define extension functions anywhere, which enables you to create extension-oriented designs. These designs separate
68+
core functionality from useful but non-essential features, making your code easier to read and maintain.
69+
70+
A good example is the [`HttpClient`](https://api.ktor.io/ktor-client/ktor-client-core/io.ktor.client/-http-client/index.html) class from the Ktor library, which helps perform network requests. The core of
71+
its functionality is a single function `request()`, which takes all the information needed for an HTTP request:
72+
73+
```kotlin
74+
class HttpClient {
75+
fun request(method: String, url: String, headers: Map<String, String>): HttpResponse {
76+
// Network code
77+
}
78+
}
79+
```
80+
{validate="false"}
81+
82+
In practice, the most popular HTTP requests are GET or POST requests. It makes sense for the library to provide shorter
83+
names for these common use cases. However, these don't require writing new network code, only a specific request call.
84+
In other words, they are perfect candidates to be defined as separate `.get()` and `.post()` extension functions:
85+
86+
```kotlin
87+
fun HttpClient.get(url: String): HttpResponse = request("GET", url, emptyMap())
88+
fun HttpClient.post(url: String): HttpResponse = request("POST", url, emptyMap())
89+
```
90+
{validate="false"}
91+
92+
These `.get()` and `.post()` functions call the `request()` function with the correct HTTP method, so you don't have to.
93+
They streamline your code and make it easier to understand:
94+
95+
```kotlin
96+
class HttpClient {
97+
fun request(method: String, url: String, headers: Map<String, String>): HttpResponse {
98+
println("Requesting $method to $url with headers: $headers")
99+
return HttpResponse("Response from $url")
100+
}
101+
}
102+
103+
fun HttpClient.get(url: String): HttpResponse = request("GET", url, emptyMap())
104+
105+
fun main() {
106+
val client = HttpClient()
107+
108+
// Making a GET request using request() directly
109+
val getResponseWithMember = client.request("GET", "https://example.com", emptyMap())
110+
111+
// Making a GET request using the get() extension function
112+
val getResponseWithExtension = client.get("https://example.com")
113+
}
114+
```
115+
{validate="false"}
116+
117+
This extension-oriented approach is widely used in Kotlin's [standard library](https://kotlinlang.org/api/latest/jvm/stdlib/)
118+
and other libraries. For example, the `String` class has many [extension functions](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/#extension-functions)
119+
to help you work with strings.
120+
121+
For more information about extension functions, see [Extensions](extensions.md).
122+
123+
## Practice
124+
125+
### Exercise 1 {initial-collapse-state="collapsed" collapsible="true" id="extension-functions-exercise-1"}
126+
127+
Write an extension function called `isPositive` that takes an integer and checks whether it is positive.
128+
129+
|---|---|
130+
```kotlin
131+
fun Int.// Write your code here
132+
133+
fun main() {
134+
println(1.isPositive())
135+
// true
136+
}
137+
```
138+
{validate="false" kotlin-runnable="true" kotlin-min-compiler-version="1.3" id="kotlin-tour-extension-functions-exercise-1"}
139+
140+
|---|---|
141+
```kotlin
142+
fun Int.isPositive(): Boolean = this > 0
143+
144+
fun main() {
145+
println(1.isPositive())
146+
// true
147+
}
148+
```
149+
{initial-collapse-state="collapsed" collapsible="true" collapsed-title="Example solution" id="kotlin-tour-extension-functions-solution-1"}
150+
151+
### Exercise 2 {initial-collapse-state="collapsed" collapsible="true" id="extension-functions-exercise-2"}
152+
153+
Write an extension function called `toLowercaseString` that takes a string and returns a lowercase version.
154+
155+
<deflist collapsible="true">
156+
<def title="Hint">
157+
Use the <a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.text/lowercase.html"> <code>.lowercase()</code>
158+
</a> function for the <code>String</code> type.
159+
</def>
160+
</deflist>
161+
162+
|---|---|
163+
```kotlin
164+
fun // Write your code here
165+
166+
fun main() {
167+
println("Hello World!".toLowercaseString())
168+
// hello world!
169+
}
170+
```
171+
{validate="false" kotlin-runnable="true" kotlin-min-compiler-version="1.3" id="kotlin-tour-extension-functions-exercise-2"}
172+
173+
|---|---|
174+
```kotlin
175+
fun String.toLowercaseString(): String = this.lowercase()
176+
177+
fun main() {
178+
println("Hello World!".toLowercaseString())
179+
// hello world!
180+
}
181+
```
182+
{initial-collapse-state="collapsed" collapsible="true" collapsed-title="Example solution" id="kotlin-tour-extension-functions-solution-2"}
183+
184+
## Next step
185+
186+
[Intermediate: Scope functions](kotlin-tour-intermediate-scope-functions.md)

docs/topics/tour/kotlin-tour-null-safety.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@ fun main() {
206206
207207
## What's next?
208208
209-
Congratulations! Now that you have completed the Kotlin tour, check out our tutorials for popular Kotlin applications:
209+
Congratulations! Now that you have completed the beginner tour, take your understanding of Kotlin to the next level with
210+
our intermediate tour:
210211
211-
* [Create a backend application](jvm-create-project-with-spring-boot.md)
212-
* [Create a cross-platform application for Android and iOS](https://www.jetbrains.com/help/kotlin-multiplatform-dev/multiplatform-create-first-app.html)
212+
<a href="kotlin-tour-intermediate-extension-functions.md"><img src="start-intermediate-tour.svg" width="700" alt="Start the intermediate Kotlin tour" style="block"/></a>

0 commit comments

Comments
 (0)