Swift में Generics और टाइपिज़ेशन: ऐसा कोड लिखना जो आपके लिए काम करे

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

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

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

जेनेरिक्स के बिना आपका Swift-कोड जल्द ही स्पेगेटी में क्यों बदल जाएगा

\n\n

कल्पना करें कि आप पिज़्ज़ा डिलीवरी के लिए एक ऐप लिख रहे हैं। आपको ऑर्डर, ग्राहक, कूरियर को प्रोसेस करना होगा — और हर बार सॉर्टिंग, सर्च या फ़िल्टरिंग के लिए एक ही कोड लिखना होगा, केवल डेटा प्रकार बदलते हुए? यह किसी भी डेवलपर के लिए एक बुरा सपना लगता है। यहीं पर Swift में Generics मंच पर आते हैं — एक शक्तिशाली उपकरण जो आपको टाइप सुरक्षा से समझौता किए बिना लचीला, पुन: प्रयोज्य कोड लिखने की अनुमति देता है।

\n\n

इस लेख में हम केवल सिंटैक्स पर नहीं चलेंगे। हम समझेंगे कि Swift में टाइपिज़ेशन और जेनेरिक्स एक साथ कैसे काम करते हैं, ताकि आपका कोड न केवल सुंदर हो बल्कि विश्वसनीय भी हो। आप सीखेंगे कि कॉपी-पेस्ट से कैसे छुटकारा पाएं, protocol को associatedtype के साथ कैसे उपयोग करें और क्यों where-क्लॉज़ आपके सबसे अच्छे दोस्त हैं।

\n\n

Generics क्या हैं और वे खेल के नियम क्यों बदलते हैं

\n\n

Generics (जेनेरिक्स, सामान्यीकृत प्रकार) एक तंत्र है जो आपको फ़ंक्शन, स्ट्रक्चर, क्लास और एनुम लिखने की अनुमति देता है जो किसी भी डेटा प्रकार के साथ काम करते हैं जो कुछ शर्तों को पूरा करता है। Int, String और Double के लिए फ़ंक्शन के तीन संस्करण लिखने के बजाय, आप एक लिखते हैं जो किसी भी प्रकार के साथ काम करता है।

\n\n

Swift में टाइपिज़ेशन सख्त और स्थिर है। इसका मतलब है कि कंपाइलर कंपाइलेशन के समय प्रकारों की जाँच करता है। Generics इस नियम का उल्लंघन नहीं करते — वे इसे और अधिक लचीला बनाते हैं। कंपाइलर फ़ंक्शन को कॉल करते समय विशिष्ट प्रकार का अनुमान लगाता है, लेकिन जाँच बनी रहती है।

\n\n

पहला उदाहरण: जेनेरिक्स के बिना फ़ंक्शन

\n\n
// बुरा: तीन प्रकारों के लिए तीन फ़ंक्शन\nfunc swapInts(_ a: inout Int, _ b: inout Int) {\n    let temp = a\n    a = b\n    b = temp\n}\n\nfunc swapStrings(_ a: inout String, _ b: inout String) {\n    let temp = a\n    a = b\n    b = temp\n}\n\nfunc swapDoubles(_ a: inout Double, _ b: inout Double) {\n    let temp = a\n    a = b\n    b = temp\n}
\n\n

और अब — जेनेरिक्स के साथ एक सुरुचिपूर्ण समाधान:

\n\n
// अच्छा: सभी प्रकारों के लिए एक फ़ंक्शन\nfunc swapValues<T>(_ a: inout T, _ b: inout T) {\n    let temp = a\n    a = b\n    b = temp\n}\n\n// उपयोग:\nvar x = 10\nvar y = 20\nswapValues(&x, &y) // T = Int\n\nvar name1 = "Alice"\nvar name2 = "Bob"\nswapValues(&name1, &name2) // T = String
\n\n

जादू देखा? <T> एक प्रकार का प्लेसहोल्डर (भराव) है। कंपाइलर कॉल करते समय वास्तविक प्रकार को स्वयं प्रतिस्थापित करता है। यही Swift में सामान्यीकृत प्रोग्रामिंग का आधार है।

\n\n

Generic-प्रकार: अपना स्वयं का सार्वभौमिक स्टैक बनाना

\n\n

Swift में जेनेरिक्स न केवल फ़ंक्शन के साथ बल्कि पूरे प्रकारों के साथ भी काम करते हैं। आइए एक Stack स्ट्रक्चर बनाएं — LIFO (Last In, First Out) डेटा संरचना का एक उत्कृष्ट उदाहरण।

\n\n
struct Stack<Element> {\n    private var items: [Element] = []\n    \n    mutating func push(_ item: Element) {\n        items.append(item)\n    }\n    \n    mutating func pop() -> Element? {\n        return items.popLast()\n    }\n    \n    func peek() -> Element? {\n        return items.last\n    }\n    \n    var count: Int {\n        return items.count\n    }\n}\n\n// उपयोग:\nvar intStack = Stack<Int>()\nintStack.push(1)\nintStack.push(2)\nintStack.push(3)\nprint(intStack.pop() ?? 0) // 3\n\nvar stringStack = Stack<String>()\nstringStack.push("Swift")\nstringStack.push("Generics")\nprint(stringStack.peek() ?? "") // "Generics"
\n\n

ध्यान दें: हम स्ट्रक्चर घोषित करते समय कोण कोष्ठक में Element प्रकार निर्दिष्ट करते हैं। इंस्टेंस बनाते समय हम इसे विशिष्ट करते हैं — Stack<Int> या Stack<String>। कंपाइलर गारंटी देता है कि आप गलती से पूर्णांकों के स्टैक में एक स्ट्रिंग नहीं डाल सकते।

\n\n

associatedtype के साथ Protocol: प्रोटोकॉल के लिए जेनेरिक्स

\n\n

Swift में, प्रोटोकॉल में सीधे generic-पैरामीटर नहीं हो सकते। इसके बजाय, उपयोग करें

ब्लॉग

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