Swift में == और ===: अंतर क्या है और अंदर क्या होता है

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

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

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

Swift में समानता के दो चिह्न क्यों हैं और वे क्या छिपाते हैं?

\n\n

क्या आपने कभी Swift में कोड लिखा है और अचानक एक अजीब ऑपरेटर === देखा है? पहला विचार: "टाइपिंग की गलती? या यह कोई सुपर-बराबर है?" वास्तव में, यह कोई टाइपिंग गलती नहीं है, बल्कि एक शक्तिशाली तंत्र है जो तुलना के तर्क को पूरी तरह से बदल देता है। यदि आप क्लास, स्ट्रक्चर या क्लोजर के साथ काम करते हैं, तो == और === के बीच अंतर को समझना कोई सिद्धांत नहीं, बल्कि एक आवश्यकता है। इसके बिना, आपको ऐसी बग मिलने का जोखिम है जिन्हें पकड़ना मुश्किल है।

\n\n

इस लेख में, हम Swift के "अंदर" झांकेंगे, समझेंगे कि दोनों ऑपरेटर कैसे काम करते हैं, और प्रत्येक कार्य के लिए सही उपकरण चुनना सीखेंगे। तैयार हैं? चलिए शुरू करते हैं।

\n\n

समानता ऑपरेटर == क्या है?

\n\n

ऑपरेटर == मानों की तुलना करने के लिए आपका मानक "दोस्त" है। यह जाँचता है कि क्या दो ऑब्जेक्ट उनकी सामग्री के आधार पर बराबर हैं। लेकिन एक बात है: Swift को यह नहीं पता होता कि आपके स्वयं के डेटा प्रकार के लिए "बराबर" का क्या अर्थ है। इसलिए, == का उपयोग करने के लिए, आपके प्रकार को Equatable प्रोटोकॉल का पालन करना होगा।

\n\n

यहाँ बताया गया है कि यह बिल्ट-इन प्रकारों के लिए कैसे दिखता है:

\n\n
let a = 5\nlet b = 5\nprint(a == b) // true, क्योंकि मान समान हैं\n\nlet name1 = "Alice"\nlet name2 = "Alice"\nprint(name1 == name2) // true, स्ट्रिंग्स समान हैं
\n\n

क्लास और स्ट्रक्चर के लिए, आपको स्वयं Equatable को लागू करना होगा। उदाहरण के लिए:

\n\n
struct User {\n    let id: Int\n    let name: String\n}\n\nextension User: Equatable {\n    static func == (lhs: User, rhs: User) -> Bool {\n        return lhs.id == rhs.id && lhs.name == rhs.name\n    }\n}\n\nlet user1 = User(id: 1, name: "John")\nlet user2 = User(id: 1, name: "John")\nprint(user1 == user2) // true, सामग्री मेल खाती है
\n\n

ध्यान दें: == मानों की तुलना करता है, न कि संदर्भों की। स्ट्रक्चर के लिए यह स्पष्ट है, लेकिन क्लास के साथ सबसे दिलचस्प शुरू होता है।

\n\n

पहचान ऑपरेटर ===: जब दो ऑब्जेक्ट एक ही चीज़ हों

\n\n

ऑपरेटर === (ट्रिपल बराबर) सामग्री की नहीं, बल्कि संदर्भों की पहचान की जाँच करता है। यह इस प्रश्न का उत्तर देता है: "क्या दो वेरिएबल मेमोरी में एक ही ऑब्जेक्ट की ओर इशारा करते हैं?"

\n\n

यह ऑपरेटर केवल संदर्भ प्रकारों के साथ काम करता है: क्लास और क्लोजर (क्लोजर भी संदर्भ प्रकार हैं)। स्ट्रक्चर और एनुम के लिए यह बिल्कुल मौजूद नहीं है - कंपाइलर एक त्रुटि देगा।

\n\n

उदाहरण देखें:

\n\n
class Car {\n    var model: String\n    init(model: String) {\n        self.model = model\n    }\n}\n\nlet car1 = Car(model: "Tesla")\nlet car2 = Car(model: "Tesla")\nlet car3 = car1\n\nprint(car1 == car2) // false, यदि Equatable लागू नहीं किया गया है\nprint(car1 === car2) // false, अलग-अलग ऑब्जेक्ट\nprint(car1 === car3) // true, एक ही संदर्भ
\n\n

यहाँ car1 और car2 समान सामग्री वाले दो अलग-अलग ऑब्जेक्ट हैं। और car3 car1 के समान ऑब्जेक्ट के लिए सिर्फ एक और नाम है। === यह स्पष्ट रूप से दिखाता है।

\n\n

यह अंदर कैसे काम करता है: मेमोरी और पॉइंटर्स

\n\n

अंतर को समझने के लिए, मेमोरी में झांकना होगा। जब आप क्लास का एक इंस्टेंस बनाते हैं, तो Swift हीप (heap) में उसके लिए एक क्षेत्र आवंटित करता है और उस क्षेत्र का एक पॉइंटर लौटाता है। वेरिएबल स्वयं ऑब्जेक्ट को नहीं, बल्कि पॉइंटर को संग्रहीत करता है।

\n\n
    \n
  • == पॉइंटर के माध्यम से सामग्री की तुलना करता है: यह आपके Equatable कार्यान्वयन को कॉल करता है, जो ऑब्जेक्ट के फील्ड को देख सकता है।
  • \n
  • === स्वयं पॉइंटर्स की तुलना करता है: यदि दो पॉइंटर मेमोरी में एक ही पते पर ले जाते हैं, तो परिणाम true होता है।
  • \n
\n\n

स्ट्रक्चर के लिए सब कुछ सरल है: वे स्टैक (stack) में संग्रहीत होते हैं और असाइनमेंट पर कॉपी हो जाते हैं। इसलिए, उनके लिए === का कोई मतलब नहीं है - दो अलग-अलग स्ट्रक्चर हमेशा मेमोरी में अलग-अलग ऑब्जेक्ट होंगे, भले ही उनकी सामग्री

ब्लॉग

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