CodexBloom - Programming Q&A Platform

Inheritance vs Composition in Kotlin: Unclear Best Practices for Code Reusability

👀 Views: 62 đŸ’Ŧ Answers: 1 📅 Created: 2025-06-07
Kotlin OOP DesignPatterns

Quick question that's been bugging me - I've been working on this all day and I'm sure I'm missing something obvious here, but I'm currently working on a Kotlin application where I need to decide between using inheritance and composition for my class design. I've defined a base class `Vehicle` and subclasses like `Car` and `Truck`, but I also have a few utility functions that I believe should be shared across various classes. My initial approach was to use inheritance, but I've started to notice code duplication and tight coupling. Here's a simplified version of my code: ```kotlin open class Vehicle(val name: String) { open fun drive() { println("Driving $name") } } class Car(name: String) : Vehicle(name) { override fun drive() { println("Car $name is driving") } } class Truck(name: String) : Vehicle(name) { override fun drive() { println("Truck $name is driving") } } ``` However, I also have a `FuelEfficiency` utility that would be useful for both `Car` and `Truck`: ```kotlin class FuelEfficiency { fun calculateEfficiency(miles: Double, gallons: Double): Double { return miles / gallons } } ``` I'm unsure whether to extend `FuelEfficiency` to `Vehicle`, making it part of the inheritance hierarchy, or to use composition by creating an instance of `FuelEfficiency` inside my `Vehicle` subclasses. When I tried to implement it using inheritance like this, I encountered issues with method overrides and ended up with a confusing structure: ```kotlin open class Vehicle(val name: String) { open fun drive() { println("Driving $name") } } open class FuelEfficiencyVehicle(name: String) : Vehicle(name) { val fuelEfficiency = FuelEfficiency() } ``` This caused me to face issues with clarity and maintainability in my code. I feel like using composition would allow better flexibility, but I'm also concerned about potential performance impacts when instantiating multiple utility classes. What are the best practices in this case? Should I stick with inheritance, or is composition clearly the better choice for the long-term maintainability of my design? Any code examples showing a better approach would be greatly appreciated! Any ideas what could be causing this? The project is a microservice built with Kotlin. Thanks for any help you can provide! Thanks in advance!