Skip to content

Commit 780347b

Browse files
committed
feat: add Kotlin intermediate tour objects
1 parent 63bf948 commit 780347b

File tree

2 files changed

+338
-0
lines changed

2 files changed

+338
-0
lines changed

docs/kr.tree

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
<toc-element hidden="true" topic="kotlin-tour-intermediate-scope-functions.md"/>
1616
<toc-element hidden="true" topic="kotlin-tour-intermediate-lambdas-receiver.md"/>
1717
<toc-element hidden="true" topic="kotlin-tour-intermediate-classes-interfaces.md"/>
18+
<toc-element hidden="true" topic="kotlin-tour-intermediate-objects.md"/>
1819
</toc-element>
1920
<toc-element toc-title="Kotlin overview">
2021
<toc-element topic="multiplatform.topic"/>
Lines changed: 337 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,337 @@
1+
[//]: # (title: Intermediate: Objects)
2+
3+
<tldr>
4+
<p><img src="icon-1-done.svg" width="20" alt="First step" /> <a href="kotlin-tour-intermediate-extension-functions.md">Extension functions</a><br />
5+
<img src="icon-2-done.svg" width="20" alt="Second step" /> <a href="kotlin-tour-intermediate-scope-functions.md">Scope functions</a><br />
6+
<img src="icon-3-done.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-done.svg" width="20" alt="Fourth step" /> <a href="kotlin-tour-intermediate-classes-interfaces.md">Classes and interfaces</a><br />
8+
<img src="icon-5.svg" width="20" alt="Fourth step" /> <strong>Objects</strong><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 expand your understanding of classes by exploring object declarations. This knowledge will help
16+
you efficiently manage behavior across your projects.
17+
18+
## Object declarations
19+
20+
In Kotlin, you can use **object declarations** to declare a class with a single instance. In a sense, you declare the
21+
class and create the single instance _at the same time_. Object declarations are useful when you want to create a class to
22+
use as a single reference point for your program or to coordinate behavior across a system.
23+
24+
> A class that has only one instance that is easily accessible is called a **singleton**.
25+
>
26+
{style="tip"}
27+
28+
Objects in Kotlin are **lazy**, meaning they are created only when accessed. Kotlin also ensures that all
29+
objects are created in a thread-safe manner so that you don't have to check this manually.
30+
31+
To create an object declaration, use the `object` keyword:
32+
33+
```kotlin
34+
object DoAuth {}
35+
```
36+
37+
Following the name of your `object`, add any properties or member functions within the object body defined by curly braces `{}`.
38+
39+
> Objects can't have constructors, so they don't have headers like classes.
40+
>
41+
{style="note"}
42+
43+
For example, let's say that you wanted to create an object called `DoAuth` that is responsible for authentication:
44+
45+
```kotlin
46+
object DoAuth {
47+
fun takeParams(username: String, password: String) {
48+
println("input Auth parameters = $username:$password")
49+
}
50+
}
51+
52+
fun main(){
53+
// The object is created when the takeParams() function is called
54+
DoAuth.takeParams("coding_ninja", "N1njaC0ding!")
55+
// input Auth parameters = coding_ninja:N1njaC0ding!
56+
}
57+
```
58+
{kotlin-runnable="true" id="kotlin-tour-object-declarations"}
59+
60+
The object has a member function called `takeParams` that accepts `username` and `password` variables as parameters
61+
and returns a string to the console. The `DoAuth` object is only created when the function is called for the first time.
62+
63+
> Objects can inherit from classes and interfaces. For example:
64+
>
65+
> ```kotlin
66+
> interface Auth {
67+
> fun takeParams(username: String, password: String)
68+
> }
69+
>
70+
> object DoAuth : Auth {
71+
> override fun takeParams(username: String, password: String) {
72+
> println("input Auth parameters = $username:$password")
73+
> }
74+
> }
75+
> ```
76+
>
77+
{style="note"}
78+
79+
#### Data objects
80+
81+
To make it easier to print the contents of an object declaration, Kotlin has **data** objects. Similar to data classes,
82+
which you learned about in the beginner tour, data objects automatically come with additional member functions:
83+
`toString()` and `equals()`.
84+
85+
> Unlike data classes, data objects do not come automatically with the `copy()` member function because they only have
86+
> a single instance that can't be copied.
87+
>
88+
{type ="note"}
89+
90+
To create a data object, use the same syntax as for object declarations but prefix it with the `data` keyword:
91+
92+
```kotlin
93+
data object AppConfig {}
94+
```
95+
96+
For example:
97+
98+
```kotlin
99+
data object AppConfig {
100+
var appName: String = "My Application"
101+
var version: String = "1.0.0"
102+
}
103+
104+
fun main() {
105+
println(AppConfig)
106+
// AppConfig
107+
108+
println(AppConfig.appName)
109+
// My Application
110+
}
111+
```
112+
{kotlin-runnable="true" id="kotlin-tour-data-objects"}
113+
114+
For more information about data objects, see [](object-declarations.md#data-objects).
115+
116+
#### Companion objects
117+
118+
In Kotlin, a class can have an object: a **companion** object. You can only have **one** companion object per class.
119+
A companion object is created only when its class is referenced for the first time.
120+
121+
Any properties or functions declared inside a companion object are shared across all class instances.
122+
123+
To create a companion object within a class, use the same syntax for an object declaration but prefix it with the `companion`
124+
keyword:
125+
126+
```kotlin
127+
companion object Bonger {}
128+
```
129+
130+
> A companion object doesn't have to have a name. If you don't define one, the default is `Companion`.
131+
>
132+
{style="note"}
133+
134+
To access any properties or functions of the companion object, reference the class name. For example:
135+
136+
```kotlin
137+
class BigBen {
138+
companion object Bonger {
139+
fun getBongs(nTimes: Int) {
140+
repeat(nTimes) { print("BONG ") }
141+
}
142+
}
143+
}
144+
145+
fun main() {
146+
// Companion object is created when the class is referenced for the
147+
// first time.
148+
BigBen.getBongs(12)
149+
// BONG BONG BONG BONG BONG BONG BONG BONG BONG BONG BONG BONG
150+
}
151+
```
152+
{kotlin-runnable="true" kotlin-min-compiler-version="1.3" id="kotlin-tour-classes-companion-object"}
153+
154+
This example creates a class called `BigBen` that contains a companion object called `Bonger`. The companion object
155+
has a member function called `getBongs()` that accepts an integer and prints `"BONG"` to the console the same number of times
156+
as the integer.
157+
158+
In the `main()` function, the `getBongs()` function is called by referring to the class name. The companion object is created
159+
at this point. The `getBongs()` function is called with parameter `12`.
160+
161+
For more information, see [](object-declarations.md#companion-objects).
162+
163+
## Object declarations practice
164+
165+
### Exercise 1 {initial-collapse-state="collapsed" collapsible="true" id="objects-exercise-1"}
166+
167+
You run a coffee shop and have a system for tracking customer orders. Consider the code below and complete the declaration
168+
of the second data object so that the following code in the `main()` function runs successfully:
169+
170+
|---|---|
171+
172+
```kotlin
173+
interface Order {
174+
val orderId: String
175+
val customerName: String
176+
val orderTotal: Double
177+
}
178+
179+
data object OrderOne: Order {
180+
override val orderId = "001"
181+
override val customerName = "Alice"
182+
override val orderTotal = 15.50
183+
}
184+
185+
data object // Write your code here
186+
187+
fun main() {
188+
// Print the contents of each data object
189+
println("Order One Details: $OrderOne")
190+
println("Order Two Details: $OrderTwo")
191+
192+
// Check if the orders are identical
193+
println("Are the two orders identical? ${OrderOne == OrderTwo}")
194+
195+
if (OrderOne == OrderTwo) {
196+
println("The orders are identical.")
197+
} else {
198+
println("The orders are unique.")
199+
}
200+
201+
println("Do the orders have the same customer name? ${OrderOne.customerName == OrderTwo.customerName}")
202+
}
203+
```
204+
{validate="false" kotlin-runnable="true" kotlin-min-compiler-version="1.3" id="kotlin-tour-objects-exercise-1"}
205+
206+
|---|---|
207+
```kotlin
208+
interface Order {
209+
val orderId: String
210+
val customerName: String
211+
val orderTotal: Double
212+
}
213+
214+
data object OrderOne: Order {
215+
override val orderId = "001"
216+
override val customerName = "Alice"
217+
override val orderTotal = 15.50
218+
}
219+
220+
data object OrderTwo: Order {
221+
override val orderId = "002"
222+
override val customerName = "Bob"
223+
override val orderTotal = 12.75
224+
}
225+
226+
fun main() {
227+
// Print the contents of each data object
228+
println("Order One Details: $OrderOne")
229+
println("Order Two Details: $OrderTwo")
230+
231+
// Check if the orders are identical
232+
println("Are the two orders identical? ${OrderOne == OrderTwo}")
233+
234+
if (OrderOne == OrderTwo) {
235+
println("The orders are identical.")
236+
} else {
237+
println("The orders are unique.")
238+
}
239+
240+
println("Do the orders have the same customer name? ${OrderOne.customerName == OrderTwo.customerName}")
241+
}
242+
```
243+
{initial-collapse-state="collapsed" collapsible="true" collapsed-title="Example solution" id="kotlin-tour-objects-solution-1"}
244+
245+
### Exercise 2 {initial-collapse-state="collapsed" collapsible="true" id="objects-exercise-2"}
246+
247+
Create an object declaration that inherits from the `Vehicle` interface to create a unique vehicle type: `FlyingSkateboard`.
248+
Implement the `name` property and the `move()` function in your object so that the following code in the `main()` function runs
249+
successfully:
250+
251+
|---|---|
252+
253+
```kotlin
254+
interface Vehicle {
255+
val name: String
256+
fun move(): String
257+
}
258+
259+
object // Write your code here
260+
261+
fun main() {
262+
println("${FlyingSkateboard.name}: ${FlyingSkateboard.move()}")
263+
println("${FlyingSkateboard.name}: ${FlyingSkateboard.fly()}")
264+
}
265+
```
266+
{validate="false" kotlin-runnable="true" kotlin-min-compiler-version="1.3" id="kotlin-tour-objects-exercise-2"}
267+
268+
|---|---|
269+
```kotlin
270+
interface Vehicle {
271+
val name: String
272+
fun move(): String
273+
}
274+
275+
object FlyingSkateboard : Vehicle {
276+
override val name = "Flying Skateboard"
277+
override fun move() = "Glides through the air with a hover engine"
278+
279+
fun fly(): String = "Woooooooo"
280+
}
281+
282+
fun main() {
283+
println("${FlyingSkateboard.name}: ${FlyingSkateboard.move()}")
284+
println("${FlyingSkateboard.name}: ${FlyingSkateboard.fly()}")
285+
}
286+
```
287+
{initial-collapse-state="collapsed" collapsible="true" collapsed-title="Example solution" id="kotlin-tour-objects-solution-2"}
288+
289+
### Exercise 3 {initial-collapse-state="collapsed" collapsible="true" id="objects-exercise-3"}
290+
291+
You have an app where you want to record temperatures. The class itself stores the information in Celsius, but
292+
you want to provide an easy way to create an instance in Fahrenheit as well. Complete the data class so that
293+
the following code in the `main()` function runs successfully:
294+
295+
<deflist collapsible="true">
296+
<def title="Hint">
297+
Use a companion object.
298+
</def>
299+
</deflist>
300+
301+
|---|---|
302+
```kotlin
303+
data class Temperature(val celsius: Double) {
304+
val fahrenheit: Double = celsius * 9 / 5 + 32
305+
306+
// Write your code here
307+
}
308+
309+
fun main() {
310+
val fahrenheit = 90.0
311+
val temp = Temperature.fromFahrenheit(fahrenheit)
312+
println("${temp.celsius}°C is $fahrenheit °F")
313+
}
314+
```
315+
{validate="false" kotlin-runnable="true" kotlin-min-compiler-version="1.3" id="kotlin-tour-objects-exercise-3"}
316+
317+
|---|---|
318+
```kotlin
319+
data class Temperature(val celsius: Double) {
320+
val fahrenheit: Double = celsius * 9 / 5 + 32
321+
322+
companion object {
323+
fun fromFahrenheit(fahrenheit: Double): Temperature = Temperature((fahrenheit - 32) * 5 / 9)
324+
}
325+
}
326+
327+
fun main() {
328+
val fahrenheit = 90.0
329+
val temp = Temperature.fromFahrenheit(fahrenheit)
330+
println("${temp.celsius}°C is $fahrenheit °F")
331+
}
332+
```
333+
{initial-collapse-state="collapsed" collapsible="true" collapsed-title="Example solution" id="kotlin-tour-objects-solution-3"}
334+
335+
## Next step
336+
337+
[Intermediate: Open and special classes](kotlin-tour-intermediate-open-special-classes.md)

0 commit comments

Comments
 (0)