Have you ever encountered situations in Kotlin where multiple declarations in the same scope share the same name? This is known as shadowing. In such cases, it can be unclear which function or variable is being referred to. But don’t worry! Kotlin offers a simple trick to resolve this issue using fully qualified names to unambiguously pick the right declaration.
Want to explore other Kotlin techniques? Check out my guide on Kotlin 2.0 Key Updates.

What is Shadowing in Kotlin? 🧐
Shadowing occurs when two or more declarations in the same scope have the same name. This could be two functions, variables, or any other declarations that lead to a naming conflict. The question arises: Which one does Kotlin use? In most cases, the inner scope declaration shadows the outer one. Let’s look at an example:
fun printMessage() {
println("Hello from printMessage!")
}
fun main() {
fun printMessage() {
println("Hello from main's printMessage!")
}
printMessage() // Which function gets called?
}
In the above snippet, the printMessage
function defined inside main
shadows the one outside of it. Therefore, calling printMessage()
within main
executes the inner function.
How to Resolve Shadowing with Fully Qualified Names 🚀
To resolve conflicts caused by shadowing, you can use fully qualified names. A fully qualified name includes the package name and any outer class names that the declaration is nested within.
fun printMessage() {
println("Hello from outer printMessage!")
}
fun main() {
fun printMessage() {
println("Hello from inner printMessage!")
}
// Calling the inner function
printMessage() // Outputs: Hello from inner printMessage!
// Calling the outer function using its fully qualified name
com.example.printMessage() // Outputs: Hello from outer printMessage!
}
In this example, the inner printMessage()
is still called by default, but using the fully qualified name com.example.printMessage()
allows us to access the outer function.
Why Use Fully Qualified Names?
Using fully qualified names can be particularly useful when:
- You’re working in a large codebase with similarly named declarations across different packages.
- There is a need to maintain clarity on which function or variable is being used.
- Debugging situations where unintended shadowing has occurred.
Best Practices for Avoiding Shadowing
While using fully qualified names is a great solution, here are a few best practices to avoid naming conflicts in the first place:
- Use clear and descriptive names for functions and variables.
- Avoid nested scopes with similarly named declarations.
- Group related functions into appropriately named packages.
More on Kotlin Tricks
If you are looking to dive deeper into Kotlin and learn about other techniques and best practices, I have an article on Concurrency in Kotlin Using Coroutines that you might find useful!
Did you like this article?
You can subscribe to my newsletter below and get updates about my new articles.