Extensions in Kotlin add new functions to classes without changing them. They are resolved based on the type known at compile time, not the actual object type at runtime.
Extensions resolved statically in Kotlin
fun ClassName.newFunction() { // function body }
fun String.addExclamation() = this + "!"
fun Int.isEven() = this % 2 == 0
open class Base class Derived : Base() fun Base.foo() = "Base" fun Derived.foo() = "Derived" fun printFoo(b: Base) { println(b.foo()) }
Even though base holds a Derived object, the extension function called is for Base because extensions are resolved statically by the variable's declared type.
open class Base class Derived : Base() fun Base.foo() = "Base" fun Derived.foo() = "Derived" fun main() { val base: Base = Derived() println(base.foo()) }
Extension functions do not override member functions.
If a member function and an extension function have the same signature, the member function is called.
Extensions are resolved at compile time based on the variable's declared type, not the runtime type.
Extensions add functions to classes without changing them.
They are resolved statically by the declared type, not dynamically by the actual object.
This means the extension function called depends on the variable type, not the instance type.
Practice
Solution
Step 1: Understand static resolution
Static resolution means decisions are made at compile time, not runtime.Step 2: Apply to extension functions
Kotlin chooses the extension function based on the variable's declared type, ignoring the actual object type.Final Answer:
The extension function called depends on the variable's declared type, not the actual object type. -> Option BQuick Check:
Extensions resolved statically = based on declared type [OK]
- Thinking extension functions override member functions dynamically
- Assuming extension functions change the original class
- Confusing static with dynamic dispatch
greet for class Person in Kotlin?Solution
Step 1: Recall extension function syntax
Extension functions use the syntax: fun ClassName.functionName() { ... }Step 2: Match syntax to options
fun Person.greet() { println("Hello") } matches the correct syntax: fun Person.greet() { println("Hello") }Final Answer:
fun Person.greet() { println("Hello") } -> Option DQuick Check:
Extension syntax = fun ClassName.functionName() [OK]
- Using 'extension' keyword which doesn't exist
- Incorrect parameter placement
- Missing receiver type before function name
open class Base
class Derived : Base()
fun Base.foo() = "Base"
fun Derived.foo() = "Derived"
fun printFoo(b: Base) {
println(b.foo())
}
fun main() {
val d: Derived = Derived()
printFoo(d)
}What is the output when
main() runs?Solution
Step 1: Analyze parameter type in printFoo
printFoo takes a parameter of type Base, so inside printFoo, b is of type Base.Step 2: Understand extension resolution
Extension functions are resolved statically by the declared type, so b.foo() calls Base.foo(), not Derived.foo().Final Answer:
Base -> Option CQuick Check:
Extension call depends on declared type = Base [OK]
- Expecting Derived.foo() to be called dynamically
- Confusing extension with member function dispatch
- Assuming runtime type affects extension resolution
open class Animal
class Dog : Animal()
fun Animal.sound() = "Some sound"
fun Dog.sound() = "Bark"
fun main() {
val animal: Animal = Dog()
println(animal.sound())
}Solution
Step 1: Check for compilation errors
Extension functions can be overloaded by receiver type; no syntax error here.Step 2: Understand output based on static resolution
Variable animal is declared as Animal, so animal.sound() calls Animal.sound(), outputting "Some sound".Final Answer:
No error; output is "Some sound" -> Option AQuick Check:
Extension resolved by declared type = Animal.sound() [OK]
- Expecting Dog.sound() to be called dynamically
- Thinking extension functions cause runtime errors
- Confusing extension overloading with overriding
describe() to a class hierarchy where Cat inherits from Animal. You want describe() to print "Animal description" when called on an Animal variable, and "Cat description" when called on a Cat variable. Given Kotlin's static resolution of extensions, how should you design your code to achieve this behavior?Solution
Step 1: Understand static resolution impact
Extension functions are chosen by variable type, so different extensions for Animal and Cat can coexist.Step 2: Design with two extensions and variable types
Define describe() extensions for Animal and Cat separately, then call describe() on variables declared as Animal or Cat to get different outputs.Final Answer:
Declare two extension functions: one for Animal and one for Cat; call describe() on variables typed accordingly. -> Option AQuick Check:
Different extensions + variable types = desired output [OK]
- Trying to override extensions as member functions
- Relying on runtime type for extension dispatch
- Using reflection unnecessarily
Ready to prove it?
Pass the test and this pattern moves unknown
