📖 Scenario: Imagine you want to create HTML content using Kotlin code in a neat and readable way. You will build a small DSL (Domain Specific Language) using Kotlin extensions to create HTML tags easily.
🎯 Goal: Build a Kotlin program that uses extension functions to create a simple HTML DSL. You will define tags and nest them, then print the generated HTML string.
📋 What You'll Learn
Create a class called HTML with a content property to hold the HTML string.
Create an extension function html on HTML to add the <html> tag.
Create extension functions head and body on HTML to add <head> and <body> tags.
Use lambda parameters to allow nesting tags inside each other.
Print the final HTML string.
💡 Why This Matters
🌍 Real World
Building DSLs like this helps developers write code that looks like the language they want to generate, such as HTML, SQL, or configuration files.
💼 Career
Many Kotlin developers use DSLs to simplify complex tasks, improve code clarity, and reduce errors in projects like web development, build scripts, or testing frameworks.
Progress0 / 4 steps
1
Create the HTML class to hold content
Create a class called HTML with a mutable property content of type StringBuilder initialized empty.
Kotlin
Hint
Use val content = StringBuilder() inside the class to store HTML text.
2
Add an extension function html to add <html> tag
Add an extension function html on HTML that takes a lambda block: HTML.() -> Unit. Inside it, append <html> to content, call block(), then append </html>.
Kotlin
Hint
Use fun HTML.html(block: HTML.() -> Unit) and call block() inside.
3
Add extension functions head and body for tags
Add extension functions head and body on HTML that take a lambda block: HTML.() -> Unit. Each should append the opening tag (<head> or <body>), call block(), then append the closing tag.
Kotlin
Hint
Define head and body similarly to html, appending tags and calling block().
4
Use the DSL to build and print HTML content
Create an HTML instance called htmlPage. Call htmlPage.html with a lambda that calls head and body. Inside head, append <title>My Page</title> to content. Inside body, append <h1>Welcome</h1>. Finally, print htmlPage.content.toString().
Kotlin
Hint
Use htmlPage.html { head { ... } body { ... } } and append strings inside lambdas. Then print the content.
Practice
(1/5)
1. What is the main purpose of using extensions in Kotlin for DSL building?
easy
A. To add new functions to existing classes without modifying their source code
B. To create new classes from scratch
C. To change the behavior of existing functions permanently
D. To restrict access to class members
Solution
Step 1: Understand what extensions do
Extensions allow adding new functions to existing classes without changing their original code.
Step 2: Relate to DSL building
This helps create readable DSLs by extending classes with custom functions.
Final Answer:
To add new functions to existing classes without modifying their source code -> Option A
Quick Check:
Extensions add functions without modifying classes [OK]
Hint: Extensions add functions without changing original classes [OK]
2. Which of the following is the correct syntax to define an extension function greet for the String class in Kotlin?
easy
A. extension fun String greet() { println("Hello") }
B. fun greet(String) { println("Hello") }
C. fun String.greet() { println("Hello") }
D. fun greet() String { println("Hello") }
Solution
Step 1: Recall extension function syntax
Extension functions are declared with fun ClassName.functionName().
Step 2: Match syntax to options
fun String.greet() { println("Hello") } uses fun String.greet(), which is correct syntax.
Final Answer:
fun String.greet() { println("Hello") } -> Option C
Quick Check:
Extension syntax = fun ClassName.functionName() [OK]
Hint: Extension syntax: fun ClassName.functionName() [OK]
Common Mistakes:
Placing class name as parameter instead of receiver
Using 'extension' keyword which doesn't exist
Incorrect function return type placement
3. What will be the output of the following Kotlin code?
class Box(var content: String)
fun Box.describe() = "Box contains: $content"
fun main() {
val box = Box("Apples")
println(box.describe())
}
medium
A. Box contains: Apples
B. Box contains: content
C. Compilation error
D. Box@<memory_address>
Solution
Step 1: Understand the extension function
The extension function describe returns a string with the content property of Box.
Step 2: Check the main function output
Creating Box("Apples") and calling describe() prints "Box contains: Apples".
Final Answer:
Box contains: Apples -> Option A
Quick Check:
Extension uses property value correctly [OK]
Hint: Extension functions use class properties directly [OK]
Common Mistakes:
Expecting 'content' literal instead of property value
Confusing extension with overriding toString()
Thinking it prints memory address
4. Identify the error in this Kotlin code snippet that tries to build a simple DSL using extensions:
class Menu {
val items = mutableListOf<String>()
}
fun Menu.addItem(name: String) {
items.add(name)
}
fun buildMenu(block: Menu.() -> Unit): Menu {
val menu = Menu()
block(menu)
return menu
}
fun main() {
val menu = buildMenu {
addItem("Home")
addItem("About")
}
println(menu.items)
}
medium
A. The extension function addItem should be inside the Menu class
B. The block should be called with menu.block() instead of block(menu)
C. MutableList should be immutableList
D. No error, code runs correctly
Solution
Step 1: Understand the block parameter type
The block is a lambda with receiver: Menu.() -> Unit, so it should be called as menu.block().
Step 2: Identify the call mistake
The code calls block(menu), which treats block as a normal function, causing an error.
Final Answer:
The block should be called with menu.block() instead of block(menu) -> Option B
Quick Check:
Lambda with receiver called as receiver.lambda() [OK]
Hint: Call lambdas with receiver as receiver.lambda() [OK]
Common Mistakes:
Calling lambda with receiver as normal function
Placing extension function inside class unnecessarily
Confusing mutable and immutable lists
5. Given the following Kotlin DSL code, what is the output?
class Html {
val children = mutableListOf<String>()
}
fun Html.body(block: Html.() -> Unit) {
this.block()
}
fun Html.p(text: String) {
children.add("
$text
")
}
fun html(block: Html.() -> Unit): Html {
val html = Html()
html.block()
return html
}
fun main() {
val page = html {
body {
p("Hello")
p("World")
}
}
println(page.children)
}
hard
A. Compilation error due to missing body class
B. []
C. ["
Hello
World
"]
D. ["
Hello
", "
World
"]
Solution
Step 1: Trace the DSL calls
The html function creates an Html object and calls body extension, which calls p twice adding paragraphs to children.
Step 2: Check the children list content
Both p calls add strings "
Hello
" and "
World
" to the children list.
Final Answer:
["
Hello
", "
World
"] -> Option D
Quick Check:
Extensions build nested structure as list of strings [OK]
Hint: Extensions add elements to list step-by-step [OK]
Common Mistakes:
Expecting nested tags as single string
Assuming body creates separate object
Thinking code causes compilation error
Recommended
Ready to prove it?
Pass the test and this pattern moves unknownstrongwhile earning +1 Grip toward your certificate.