परिचय
Kotlin `data class` स्वचालित रूप से `equals()`, `hashCode()`, `toString()`, `copy()`, `componentN()` उत्पन्न करता है। लेकिन `data class` को `open` नहीं किया जा सकता (सीधे विस्तार योग्य नहीं)।
डेटा क्लास प्रतिबंध
- प्राथमिक कंस्ट्रक्टर में कम से कम एक पैरामीटर
- सभी पैरामीटर `val` या `var` होने चाहिए
- `abstract`, `open`, `sealed`, `inner` नहीं हो सकता
- इसलिए **सीधे विस्तार नहीं किया जा सकता**
समाधान: सुपर क्लास + कंपोजिशन/विरासत
पैटर्न 1: बेस क्लास (Abstract/Open) + डेटा क्लास उपवर्ग
// बेस क्लास (open/abstract)
abstract class Resource {
abstract var id: Long
abstract var location: String
// सामान्य व्यवहार
fun describe() = "Resource(id=$id, location=$location)"
}
// डेटा क्लास बेस को लागू करती है
data class Book(
override var id: Long = 0,
override var location: String = "",
val isbn: String,
val title: String
) : Resource()
fun main() {
val book = Book(1L, "India", "123456", "Kotlin in Action")
println(book) // toString() से
println(book.describe()) // बेस क्लास मेथड
println("ISBN: ${book.isbn}")
}
आउटपुट
Book(id=1, location=India, isbn=123456, title=Kotlin in Action) Resource(id=1, location=India) ISBN: 123456
पैटर्न 2: सील्ड क्लास हायरार्की (जब सीमित उपप्रकार हों)
sealed class Resource {
data class Book(
val isbn: String,
val title: String,
val author: String
) : Resource()
data class Article(
val url: String,
val publishDate: String
) : Resource()
data class Video(
val duration: Int,
val quality: String
) : Resource()
}
fun processResource(resource: Resource) = when (resource) {
is Resource.Book -> println("पुस्तक: ${resource.title} by ${resource.author}")
is Resource.Article -> println("लेख: ${resource.url}")
is Resource.Video -> println("वीडियो: ${resource.duration}मिनट")
}
fun main() {
val items = listOf(
Resource.Book("123", "Kotlin Guide", "Author"),
Resource.Article("https://example.com", "2024-01-15"),
Resource.Video(45, "1080p")
)
items.forEach(::processResource)
}
पैटर्न 3: कंपोजिशन (विरासत के बजाय)
// बेस डेटा
data class BaseInfo(
val id: Long,
val createdAt: String
)
// डेटा क्लास जिसमें बेस शामिल है
data class User(
val baseInfo: BaseInfo,
val name: String,
val email: String
) {
// सुविधा प्रॉपर्टीज
val id: Long get() = baseInfo.id
val createdAt: String get() = baseInfo.createdAt
// copy() बेस को भी कॉपी करता है
fun withName(newName: String) = copy(name = newName)
}
fun main() {
val base = BaseInfo(1, "2024-01-01")
val user = User(base, "John", "john@example.com")
println(user)
println("ID: ${user.id}")
}
पैटर्न 4: इंटरफेस + डेटा क्लास
interface Identifiable {
val id: Long
}
interface Timestamped {
val createdAt: String
}
data class Entity(
override val id: Long,
override val createdAt: String,
val data: String
) : Identifiable, Timestamped
fun main() {
val entity = Entity(1, "2024-01-01", "Data")
println(entity)
// इंटरफेस के रूप में उपयोग
val identifiable: Identifiable = entity
println("ID: ${identifiable.id}")
}
क्यों डेटा क्लास ओपन नहीं हो सकती?
- `equals()`/`hashCode()` कॉन्ट्रैक्ट: उपवर्ग अतिरिक्त प्रॉपर्टीज जोड़ सकते हैं, जिससे समरूपता टूटती है
- `copy()` व्यवहार: उपवर्ग प्रॉपर्टीज कैसे कॉपी हों?
- `componentN()` क्रम: उपवर्ग कंपोनेंट्स कहां फिट हों?
सर्वोत्तम अभ्यास
- सील्ड क्लास - जब निश्चित उपप्रकार सेट हो (सबसे इडिओमैटिक)
- कंपोजिशन - जब लचीलेपन की आवश्यकता हो (डेटा क्लास में डेटा क्लास)
- इंटरफेस - जब सामान्य व्यवहार साझा करना हो
- बेस ओपन क्लास - जब साझा स्टेट/व्यवहार हो और डेटा क्लास इसे लागू करे