0
0
Kotlinprogramming~15 mins

Overriding methods with override in Kotlin - Deep Dive

Choose your learning style9 modes available
Overview - Overriding methods with override
What is it?
Overriding methods with override in Kotlin means creating a new version of a function in a subclass that replaces the function with the same name in its parent class. This allows the subclass to provide its own specific behavior while keeping the same function name. The keyword override is used to clearly show that a method is being replaced. This helps Kotlin check that the method actually exists in the parent class and prevents mistakes.
Why it matters
Without method overriding, subclasses would not be able to change or extend the behavior of their parent classes easily. This would make code less flexible and harder to reuse. Overriding lets programmers write general code in a parent class and customize it in child classes, making programs easier to maintain and expand. It also helps catch errors early by requiring the override keyword.
Where it fits
Before learning method overriding, you should understand classes, inheritance, and functions in Kotlin. After mastering overriding, you can learn about polymorphism, abstract classes, and interfaces, which build on this concept to create powerful and flexible code designs.
Mental Model
Core Idea
Overriding lets a subclass replace a parent class’s method with its own version to customize behavior while keeping the same method name.
Think of it like...
Imagine a family recipe book passed down from parents to children. Each child can take the original recipe and change some ingredients or steps to make it their own special version, but it still has the same recipe name.
Parent Class
┌───────────────┐
│ fun greet()   │
│ { print("Hi") } │
└──────┬────────┘
       │
       ▼
Child Class
┌───────────────┐
│ override fun greet() │
│ { print("Hello") } │
└─────────────────────┘
Build-Up - 7 Steps
1
FoundationUnderstanding basic inheritance
🤔
Concept: Learn how a subclass inherits methods from a parent class.
In Kotlin, a class can inherit from another class using a colon. The subclass gets all the methods and properties of the parent class automatically. Example: open class Animal { fun sound() { println("Some sound") } } class Dog : Animal() { } fun main() { val dog = Dog() dog.sound() // Calls Animal's sound method }
Result
Output: Some sound
Understanding inheritance is key because overriding only works when a subclass inherits methods from a parent class.
2
FoundationDeclaring methods open for override
🤔
Concept: Learn that methods must be marked open to allow overriding.
By default, Kotlin methods are final and cannot be overridden. To allow a method to be overridden, you must mark it with the open keyword. Example: open class Animal { open fun sound() { println("Some sound") } } class Dog : Animal() { } fun main() { val dog = Dog() dog.sound() // Calls Animal's sound method }
Result
Output: Some sound
Knowing that methods are final by default helps prevent accidental overrides and enforces explicit design decisions.
3
IntermediateOverriding methods with override keyword
🤔Before reading on: do you think Kotlin allows overriding methods without the override keyword? Commit to your answer.
Concept: Learn how to override a method in a subclass using the override keyword.
To replace a parent class method, the subclass must use the override keyword. This tells Kotlin you intend to change the method. Example: open class Animal { open fun sound() { println("Some sound") } } class Dog : Animal() { override fun sound() { println("Bark") } } fun main() { val dog = Dog() dog.sound() // Calls Dog's overridden sound method }
Result
Output: Bark
Understanding the override keyword prevents silent errors and makes code intentions clear and safe.
4
IntermediateCalling the parent method with super
🤔Before reading on: do you think you can call the parent class method from an overridden method? Commit to your answer.
Concept: Learn how to call the original method from the parent class inside an overridden method using super.
Sometimes you want to add to the parent method instead of fully replacing it. You can call the parent method using super.methodName(). Example: open class Animal { open fun sound() { println("Some sound") } } class Dog : Animal() { override fun sound() { super.sound() // Calls Animal's sound println("Bark") } } fun main() { val dog = Dog() dog.sound() }
Result
Output: Some sound Bark
Knowing how to call the parent method lets you extend behavior instead of replacing it completely.
5
IntermediateOverriding properties with override
🤔
Concept: Learn that properties can also be overridden using override keyword.
Not only methods, but properties can be overridden if they are open. Example: open class Animal { open val sound: String = "Some sound" } class Dog : Animal() { override val sound: String = "Bark" } fun main() { val dog = Dog() println(dog.sound) }
Result
Output: Bark
Understanding property overriding expands your ability to customize class behavior beyond just functions.
6
AdvancedOverriding with different visibility and final keyword
🤔Before reading on: can you override a method and make it less visible or final? Commit to your answer.
Concept: Learn rules about changing visibility and using final on overridden methods.
When overriding, you can keep or increase visibility but not reduce it. Also, you can mark an overridden method as final to prevent further overriding. Example: open class Animal { protected open fun sound() { println("Some sound") } } class Dog : Animal() { public override fun sound() { println("Bark") } } class Puppy : Dog() { // Cannot override sound() here if Dog marked it final }
Result
No compile errors if visibility rules followed; prevents accidental overrides with final.
Knowing visibility and final rules helps design safe and clear class hierarchies.
7
ExpertHow Kotlin enforces override safety at compile time
🤔Before reading on: do you think Kotlin allows overriding methods that don't exist in the parent? Commit to your answer.
Concept: Learn how Kotlin uses the override keyword to check method existence and prevent errors.
Kotlin requires the override keyword to confirm you intend to override a method. If the method does not exist or is not open in the parent, the compiler throws an error. This prevents typos or accidental method hiding. Example: open class Animal { open fun sound() {} } class Dog : Animal() { override fun soud() {} // Compiler error: method not found } This strict check improves code safety and clarity.
Result
Compile-time errors prevent incorrect overrides.
Understanding Kotlin's strict override checks helps avoid subtle bugs and improves code reliability.
Under the Hood
At compile time, Kotlin checks that any method marked with override matches an open method in a superclass. The compiler then generates bytecode where the subclass method replaces the parent method in the method table. At runtime, when the method is called on an instance, the JVM uses this table to invoke the subclass's version, enabling polymorphic behavior.
Why designed this way?
Kotlin was designed to avoid common bugs in inheritance by requiring explicit override declarations. This prevents accidental method hiding and makes code intentions clear. The open keyword defaults methods to final, encouraging safer design. This approach balances flexibility with safety, unlike some languages that allow silent overrides.
Superclass (Animal)
┌─────────────────────┐
│ open fun sound()    │
│ (method table slot) │
└─────────┬───────────┘
          │
          ▼
Subclass (Dog)
┌─────────────────────┐
│ override fun sound() │
│ (overrides slot)    │
└─────────────────────┘

At runtime:
Call sound() on Dog instance → JVM looks up method table → calls Dog's sound()
Myth Busters - 4 Common Misconceptions
Quick: Can you override a method in Kotlin without using the override keyword? Commit to yes or no.
Common Belief:You can override any method by just defining a method with the same name in the subclass.
Tap to reveal reality
Reality:Kotlin requires the override keyword to override a method. Without it, the compiler treats it as a new method, not an override.
Why it matters:Without the override keyword, you might think you changed behavior, but the parent method still runs, causing bugs.
Quick: Does Kotlin allow overriding methods that are not marked open in the parent? Commit to yes or no.
Common Belief:You can override any method from the parent class regardless of its declaration.
Tap to reveal reality
Reality:Only methods marked open or abstract can be overridden. Final methods cannot be changed.
Why it matters:Trying to override a non-open method causes compile errors, but misunderstanding this can lead to frustration and wasted time.
Quick: If you override a method, does the parent method automatically get called? Commit to yes or no.
Common Belief:Overriding a method means the parent method runs first, then the subclass method.
Tap to reveal reality
Reality:The parent method runs only if you explicitly call it using super. Otherwise, it is completely replaced.
Why it matters:Assuming the parent method runs can cause logic errors and unexpected behavior.
Quick: Can you override a method and make it less visible than in the parent? Commit to yes or no.
Common Belief:You can reduce the visibility of an overridden method to make it more private.
Tap to reveal reality
Reality:Kotlin does not allow reducing visibility when overriding. You can keep or increase it only.
Why it matters:Trying to reduce visibility causes compile errors and misunderstanding this limits design flexibility.
Expert Zone
1
Overriding properties with backing fields requires understanding how Kotlin generates getters and setters behind the scenes.
2
The order of initialization in inheritance hierarchies affects when overridden methods are safe to call during construction.
3
Using final on overridden methods is a strategic design choice to prevent fragile base class problems in large codebases.
When NOT to use
Avoid overriding when you want to add behavior without replacing it; instead, consider composition or delegation. Also, do not override methods that are not designed for extension (not open), as this breaks Kotlin's safety model.
Production Patterns
In real-world Kotlin projects, overriding is used extensively in Android app development to customize lifecycle methods. Frameworks rely on open and override to allow user code to extend base classes safely. Also, sealed classes combined with overriding enable exhaustive when expressions for safer code.
Connections
Polymorphism
Overriding enables polymorphism by allowing different subclass behaviors through a common interface.
Understanding overriding is essential to grasp how polymorphism lets one interface represent many implementations.
Abstract classes and interfaces
Overriding is required to provide concrete implementations of abstract methods declared in abstract classes or interfaces.
Knowing overriding helps you implement contracts defined by abstract classes or interfaces, enabling flexible design.
Biology - Genetic inheritance
Overriding in programming is like genetic mutations where offspring inherit traits but can modify them for adaptation.
Seeing overriding as a form of controlled change in inheritance helps appreciate its role in evolution and adaptation, both in nature and code.
Common Pitfalls
#1Forgetting to mark a method as open in the parent class.
Wrong approach:open class Animal { fun sound() { println("Some sound") } } class Dog : Animal() { override fun sound() { println("Bark") } }
Correct approach:open class Animal { open fun sound() { println("Some sound") } } class Dog : Animal() { override fun sound() { println("Bark") } }
Root cause:Not understanding that methods are final by default and must be explicitly marked open to allow overriding.
#2Overriding a method without using the override keyword.
Wrong approach:open class Animal { open fun sound() { println("Some sound") } } class Dog : Animal() { fun sound() { println("Bark") } }
Correct approach:open class Animal { open fun sound() { println("Some sound") } } class Dog : Animal() { override fun sound() { println("Bark") } }
Root cause:Not using the override keyword causes Kotlin to treat the method as new, not an override.
#3Assuming the parent method runs automatically when overriding.
Wrong approach:override fun sound() { println("Bark") // No call to super.sound() }
Correct approach:override fun sound() { super.sound() println("Bark") }
Root cause:Misunderstanding that the parent method must be explicitly called with super to run.
Key Takeaways
Overriding in Kotlin requires the parent method to be open and the subclass method to use the override keyword.
The override keyword makes your intention clear and lets the compiler check for errors, improving code safety.
You can call the parent method inside an override using super to extend behavior instead of replacing it.
Properties as well as methods can be overridden to customize class behavior.
Kotlin's design enforces explicit overriding to prevent accidental bugs and encourage clear inheritance hierarchies.