Understanding ‘12’ Different Types of Kotlin Classes with Real Use Cases and Examples
Kotlin provides a variety of class types, each serving a specific purpose. Understanding these class types can help developers write more efficient and maintainable code. Let’s explore the different class types in Kotlin, their real-world use cases, and example implementations.
1. Normal Class
A normal class in Kotlin is a basic blueprint for creating objects. It defines properties and methods that describe an entity.
Use Case:
Used for defining reusable components such as Person
, Car
, or BankAccount
. It is the most common class type for object-oriented programming.
class Person(val name: String, val age: Int) {
fun greet() = "Hello, my name is $name and I am $age years old."
}
val person = Person("Sumeet", 30)
println(person.greet())
2. Data Class
A data class is used to hold data and automatically provides implementations for equals()
, hashCode()
, and toString()
. It is optimized for storing and comparing immutable data.
Use Case:
Ideal for representing domain models such as User
, Product
, or Order
, where object equality is based on the content rather than the reference.
data class User(val id: Int, val name: String, val email: String)
val user = User(1, "Sumeet", "sumeet@example.com")
println(user)
3. Object Class
An object
class is a singleton, meaning only one instance exists. This is useful for stateful components and utility functions.
Use Case:
Useful for utility classes, configurations, or global state management, ensuring a single instance is shared across the application.
object Logger {
fun log(message: String) = println("LOG: $message")
}
Logger.log("Application started")
4. Data Object Class (Kotlin 1.9+)
A data object
is a singleton version of a data class
. It combines the benefits of both object
and data class
, providing a unique identity along with data properties.
Use Case:
It represents unique constant entities, such as predefined system users or configuration settings.
data object AdminUser {
val role = "Administrator"
}
println(AdminUser.role)
5. Enum Class
An enum
class represents a fixed set of constants and is often used for representing discrete values.
Use Case:
Used for defining states, modes, or predefined options, such as HTTP status codes, user roles, or payment statuses.
enum class PaymentStatus {
PENDING, COMPLETED, FAILED
}
val status = PaymentStatus.COMPLETED
println(status)
6. Sealed Class
A sealed
class restricts class hierarchy to predefined types. It is often used in scenarios where exhaustive type-checking is needed.
Use Case:
Used for representing restricted states in state management, such as API responses that can either be Success
or Failure
.
sealed class Result {
data class Success(val data: String) : Result()
data class Failure(val error: String) : Result()
}
fun handleResult(result: Result) {
when (result) {
is Result.Success -> println("Success: ${result.data}")
is Result.Failure -> println("Failure: ${result.error}")
}
}
7. Abstract Class
An abstract
class cannot be instantiated and must be subclassed. It is used to define common behavior that must be implemented by subclasses.
Use Case:
Used for defining a common template for related classes while enforcing specific functionality in subclasses.
abstract class Vehicle(val name: String) {
abstract fun move()
}
class Car(name: String) : Vehicle(name) {
override fun move() = println("$name is driving")
}
val car = Car("Tesla")
car.move()
8. Open Class
An open
class allows inheritance, unlike normal Kotlin classes which are final by default.
Use Case:
Used when a class needs to be extended by other classes to provide additional functionality.
open class Animal(val name: String) {
open fun sound() = "Some sound"
}
class Dog(name: String) : Animal(name) {
override fun sound() = "Bark"
}
val dog = Dog("Buddy")
println(dog.sound())
9. Anonymous Class
An anonymous class is used when an instance of an interface or class is needed without formally declaring a subclass.
Use Case:
Used for quick implementations of interfaces, especially in event handling and callbacks.
interface ClickListener {
fun onClick()
}
val button = object : ClickListener {
override fun onClick() = println("Button clicked!")
}
button.onClick()
10. Value Class (Kotlin 1.5+)
A value
class is a lightweight wrapper around a single value, optimizing memory usage.
Use Case:
Used for type safety and optimization, preventing incorrect value assignments.
@JvmInline
value class Email(val value: String)
val email = Email("test@example.com")
println(email.value)
11. Annotation Class
An annotation
class is used to define metadata, which can be applied to elements in the code for tooling and reflection.
Use Case:
Used for marking elements for processing by tools or frameworks, such as dependency injection and serialization.
annotation class MyAnnotation
@MyAnnotation
class Example
12. Inner Class
An inner
class is a nested class that retains access to the outer class instance, unlike normal nested classes.
Use Case:
Used when a nested class needs to access outer class members to maintain contextual relationships.
class Outer(val outerValue: String) {
inner class Inner {
fun show() = println("Outer value: $outerValue")
}
}
val inner = Outer("Hello").Inner()
inner.show()
Conclusion
Kotlin provides different class types, each catering to specific needs. Using the appropriate class type can enhance code readability, maintainability, and efficiency. Understanding when and how to use these classes will help in building robust Kotlin applications.
Which class type do you use most often in your projects? Let me know in the comments!