Kotlin में Generics: क्यों ज़रूरी हैं और व्यवहार में कैसे उपयोग करें

शुरुआती लोगों के लिए ऑनलाइन Python प्रशिक्षक

Python आसानी से सीखें बिना सिद्धांत के बोझ के। स्वचालित जांच के साथ व्यावहारिक कार्य हल करें और ब्राउज़र में सीधे कोड लिखें।

पाठ्यक्रम शुरू करें

Kotlin में Generics: क्यों ज़रूरी हैं और व्यवहार में कैसे उपयोग करें

\n\n

Generics (सामान्यीकरण) Kotlin भाषा की प्रमुख विशेषताओं में से एक है, जो आपको अधिक लचीला, टाइप-सुरक्षित और पुन: प्रयोज्य कोड लिखने की अनुमति देता है। यदि आपने कभी List<String> या Map<Int, User> लिखा है, तो आप पहले ही जेनेरिक्स का सामना कर चुके हैं। लेकिन वास्तव में इनकी आवश्यकता क्यों है और उनसे अधिकतम लाभ कैसे उठाएं? इस लेख में हम सिद्धांत को समझेंगे और वास्तविक उदाहरणों के साथ अभ्यास की ओर बढ़ेंगे।

\n\n

समस्या जिसे Generics हल करते हैं

\n\n

कल्पना करें कि आपको एक फ़ंक्शन लिखना है जो सूची से पहला तत्व लौटाता है। जेनेरिक्स के बिना, आपको प्रत्येक डेटा प्रकार के लिए अलग फ़ंक्शन लिखना होगा:

\n\n
fun getFirstString(list: List<String>): String? = list.firstOrNull()\nfun getFirstInt(list: List<Int>): Int? = list.firstOrNull()\nfun getFirstUser(list: List<User>): User? = list.firstOrNull()
\n\n

इससे कोड की पुनरावृत्ति होती है। Any का उपयोग समस्या को हल करेगा, लेकिन आप संकलन चरण में प्रकार की जानकारी खो देंगे:

\n\n
fun getFirst(list: List<Any>): Any? = list.firstOrNull()\n\n// प्रकार रूपांतरण करना होगा\nval name: String? = getFirst(strings) as? String
\n\n

Generics इस समस्या को सुंदरता से हल करते हैं:

\n\n
fun <T> getFirst(list: List<T>): T? = list.firstOrNull()\n\n// कंपाइलर प्रकार जानता है!\nval name: String? = getFirst(listOf("Alice", "Bob"))\nval age: Int? = getFirst(listOf(25, 30))
\n\n

अब एक फ़ंक्शन किसी भी प्रकार के साथ काम करता है, पूर्ण टाइप सुरक्षा बनाए रखते हुए।

\n\n

Kotlin में Generics की मूल बातें: सिंटैक्स और घोषणा

\n\n

सामान्यीकरण को कोण कोष्ठक <T> के साथ घोषित किया जाता है। अक्षर T केवल एक परंपरा है, आप किसी भी नाम का उपयोग कर सकते हैं: E (तत्व), K (कुंजी), V (मान)।

\n\n

Generic-क्लासेस

\n\n
class Box<T>(val value: T) {\n    fun getContent(): T = value\n}\n\nfun main() {\n    val stringBox = Box("Hello")\n    val intBox = Box(42)\n    \n    println(stringBox.getContent()) // Hello\n    println(intBox.getContent())    // 42\n}
\n\n

Generic-फ़ंक्शन

\n\n
fun <T> printItem(item: T) {\n    println("Item: $item")\n}\n\n// प्रकार स्पष्ट रूप से निर्दिष्ट किया जा सकता है\nprintItem<String>("Kotlin")\n// या प्रकार अनुमान पर निर्भर रहें\nprintItem(100)
\n\n

Generic-इंटरफ़ेस

\n\n
interface Repository<T> {\n    fun getById(id: Int): T\n    fun save(item: T): Boolean\n}\n\nclass UserRepository : Repository<User> {\n    override fun getById(id: Int): User { /* ... */ }\n    override fun save(item: User): Boolean { /* ... */ }\n}
\n\n

परिवर्तनशीलता: in, out और तारांकन चिह्न *

\n\n

Kotlin की सबसे शक्तिशाली क्षमताओं में से एक परिवर्तनशीलता (variance) है। यह इस प्रश्न का उत्तर देती है: क्या List<String>, List<Any> का उपप्रकार हो सकता है?

\n\n

सहप्रसरण (out)

\n\n

out का उपयोग करें जब आपका generic-प्रकार केवल लौटाया जाता है (producer)। उदाहरण के लिए, List<T> सहप्रसरणीय है:

\n\n
// आप List<String> को List<Any> वेरिएबल में असाइन कर सकते हैं\nval strings: List<String> = listOf("a", "b")\nval anyList: List<Any> = strings // OK!\n\n// लेकिन आप तत्व नहीं जोड़ सकते\n// anyList.add(1) // संकलन त्रुटि!
\n\n

स्वयं का उदाहरण:

\n\n
class Producer<out T>(private val value: T) {\n    fun produce(): T = value\n}\n\nfun main() {\n    val stringProducer: Producer<String> = Producer("Hello")\n    val anyProducer: Producer<Any> = stringProducer // काम करता है!\n    println(anyProducer.produce())\n}
\n\n

प्रतिप्रसरण (in)

\n\n

in का उपयोग करें जब प्रकार केवल स्वीकार किया जाता है (consumer)। उदाहरण के लिए, Comparable<T>:

\n\n


                
                

ब्लॉग

पुस्तक अनुशंसाएँ