== और === के बीच का अंतर


300

स्विफ्ट में दो समानता ऑपरेटर लगते हैं: डबल बराबर ( ==) और ट्रिपल बराबर ( ===), दोनों में क्या अंतर है?

जवाबों:


149

संक्षेप में:

== ऑपरेटर जाँचता है कि क्या उनके इंस्टेंस मान बराबर हैं, "equal to"

=== ऑपरेटर जाँच करता है कि क्या संदर्भ एक ही उदाहरण को इंगित करता है, "identical to"

लंबा जवाब:

कक्षाएं संदर्भ प्रकार हैं, कई स्थिरांक और चर के लिए यह संभव है कि पर्दे के पीछे एक ही वर्ग का एक ही उदाहरण देखें। क्लास के संदर्भ रन टाइम स्टैक (आरटीएस) में रहते हैं और उनके उदाहरण मेमोरी के हीप क्षेत्र में रहते हैं। जब आप ==इसके साथ समानता को नियंत्रित करते हैं तो इसका मतलब है कि यदि उनके उदाहरण एक-दूसरे के बराबर हैं। यह समान होने के लिए समान उदाहरण होने की आवश्यकता नहीं है। इसके लिए आपको अपने कस्टम वर्ग को एक समानता मानदंड प्रदान करने की आवश्यकता है। डिफ़ॉल्ट रूप से, कस्टम कक्षाएं और संरचनाएं समतुल्य ऑपरेटरों के एक डिफ़ॉल्ट कार्यान्वयन को प्राप्त नहीं करती हैं, जिन्हें "ऑपरेटर के बराबर" ==और " ऑपरेटर के बराबर नहीं " के रूप में जाना जाता है !=। ऐसा करने के लिए आपके कस्टम वर्ग को Equatableप्रोटोकॉल की आवश्यकता होती है और यह static func == (lhs:, rhs:) -> Boolकार्य करता है

आइए उदाहरण देखें:

class Person : Equatable {
    let ssn: Int
    let name: String

    init(ssn: Int, name: String) {
        self.ssn = ssn
        self.name = name
    }

    static func == (lhs: Person, rhs: Person) -> Bool {
        return lhs.ssn == rhs.ssn
    }
}

P.S.: चूंकि ssn (सोशल सिक्योरिटी नंबर) एक अद्वितीय संख्या है, आपको यह तुलना करने की आवश्यकता नहीं है कि उनका नाम समान है या नहीं।

let person1 = Person(ssn: 5, name: "Bob")
let person2 = Person(ssn: 5, name: "Bob")

if person1 == person2 {
   print("the two instances are equal!")
}

यद्यपि व्यक्ति 1 और person2 संदर्भ हीप क्षेत्र में दो अलग-अलग उदाहरणों को इंगित करते हैं, उनके उदाहरण समान हैं क्योंकि उनके ssn संख्या समान हैं। तो आउटपुट होगाthe two instance are equal!

if person1 === person2 {
   //It does not enter here
} else {
   print("the two instances are not identical!")
}

===ऑपरेटर चेक, संदर्भ एक ही उदाहरण इंगित करता है, तो "identical to"। चूंकि H1 क्षेत्र में person1 और person2 के दो अलग-अलग उदाहरण हैं, वे समान और आउटपुट नहीं हैंthe two instance are not identical!

let person3 = person1

P.S: कक्षाएं संदर्भ प्रकार हैं और person1 के संदर्भ को इस असाइनमेंट ऑपरेशन के साथ person3 में कॉपी किया जाता है, इस प्रकार दोनों संदर्भ हीप क्षेत्र में एक ही उदाहरण को इंगित करते हैं।

if person3 === person1 {
   print("the two instances are identical!")
}

वे समान हैं और आउटपुट होगा the two instances are identical!


248

!==और ===पहचान ऑपरेटर हैं और यह निर्धारित करने के लिए उपयोग किया जाता है कि क्या दो वस्तुओं का एक ही संदर्भ है।

स्विफ्ट दो पहचान ऑपरेटर (=== और! ==) भी प्रदान करता है, जिसका उपयोग आप परीक्षण करने के लिए करते हैं कि क्या दो ऑब्जेक्ट संदर्भ दोनों एक ही ऑब्जेक्ट उदाहरण को संदर्भित करते हैं।

इसके अंश: Apple Inc. "स्विफ्ट प्रोग्रामिंग लैंग्वेज।" iBooks। https://itun.es/us/jEUH0.l


49
हाँ। ObjC से आ रहा ==है isEqual:, या वर्ग-परिभाषित अर्थ समतुल्यता है। ===स्विफ्ट ==में (ओबज) सी - सूचक समानता, या वस्तु पहचान है।
रिकस्टर

@rickster न 'मान भी एक स्मृति स्थान है? मैं अंत में वे स्मृति में कहीं हूं। क्या आप कभी उन की तुलना नहीं कर सकते? या यह है कि उनकी स्मृति स्थान कोई सार्थक मूल्य प्रदान नहीं करता है ?
शहद

2
यह सोचने के लिए कम से कम दो तरीके हैं कि भाषा बनाम स्मृति प्रकार को कैसे परिभाषित करती है। एक यह है कि किसी मान का प्रत्येक बाइंडिंग ( varया let) एक यूनिक कॉपी है - इसलिए यह पॉइंटर्स बनाने के लिए अर्थहीन है क्योंकि आपने जो पॉइंटर बनाया है वह आपके द्वारा पहले बनाए गए मूल्य से अलग मूल्य है। एक और बात यह है कि स्विफ्ट की वैल्यू सिमेंटिक एब्स्ट्रैक्ट्स की परिभाषा स्टोरेज को दूर कर देती है - कंपाइलर ऑप्टिमाइज़ करने के लिए स्वतंत्र है, जिसमें वह शामिल है और उस लाइन से परे एक मेमोरी लोकेशन पर अपनी वैल्यू को कभी भी स्टोर न करें जहाँ इसका उपयोग किया जाता है (रजिस्टर, इंस्ट्रक्शन एन्कोडिंग आदि)।
रिकसर 01

62

दोनों ऑब्जेक्टिव-सी और स्विफ्ट में, ==और !=संख्या मूल्यों के लिए मूल्य समानता के लिए ऑपरेटरों परीक्षण (जैसे, NSInteger, NSUInteger, int, ऑब्जेक्टिव-सी और में Int, UIntस्विफ्ट में आदि)। ऑब्जेक्ट्स (NSObject / NSNumber और Sub -asseses in Objective-C और Swift में संदर्भ प्रकार), ==और !=परीक्षण करें कि ऑब्जेक्ट्स / संदर्भ प्रकार समान चीज़ हैं - अर्थात, समान हैश मान - या समान समान चीज़ नहीं हैं, क्रमशः ।

let a = NSObject()
let b = NSObject()
let c = a
a == b // false
a == c // true

स्विफ्ट की पहचान समानता ऑपरेटरों, ===और !==, संदर्भगत समानता की जाँच करें - और इस प्रकार, शायद संदर्भीय समानता ऑपरेटरों IMO कहा जाना चाहिए ।

a === b // false
a === c // true

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

class MyClass: Equatable {
  let myProperty: String

  init(s: String) {
    myProperty = s
  }
}

func ==(lhs: MyClass, rhs: MyClass) -> Bool {
  return lhs.myProperty == rhs.myProperty
}

let myClass1 = MyClass(s: "Hello")
let myClass2 = MyClass(s: "Hello")
myClass1 == myClass2 // true
myClass1 != myClass2 // false
myClass1 === myClass2 // false
myClass1 !== myClass2 // true

ये समानता ऑपरेटर अन्य प्रकारों जैसे कि किसी भी भाषा में संरचनाओं के लिए लागू नहीं किए जाते हैं। हालांकि, स्विफ्ट में कस्टम ऑपरेटर बनाए जा सकते हैं, जो कि उदाहरण के लिए, आप एक सीजीपॉइंट की समानता की जांच करने के लिए ऑपरेटर बनाने में सक्षम होंगे।

infix operator <==> { precedence 130 }
func <==> (lhs: CGPoint, rhs: CGPoint) -> Bool {
  return lhs.x == rhs.x && lhs.y == rhs.y
}

let point1 = CGPoint(x: 1.0, y: 1.0)
let point2 = CGPoint(x: 1.0, y: 1.0)
point1 <==> point2 // true

3
क्षमा करें, लेकिन ओब्ज-सी में == ऑपरेटर इक्लेबिलिटी के लिए तुलना नहीं करता है, बल्कि सी - जैसे - सूचक संदर्भ (ऑब्जेक्ट आइडेंटिटी) की तुलना करता है।
मोटी श्नोर

==NSNumberउद्देश्य-सी में समानता के लिए परीक्षण नहीं करता है। NSNumberएक है NSObjectतो यह पहचान के लिए परीक्षण करती है। SOMETIMES काम करता है इसका कारण टैग किए गए पॉइंटर्स / कैश्ड ऑब्जेक्ट शाब्दिक हैं। यह गैर-शाब्दिक की तुलना करते समय बड़ी संख्या में और 32-बिट उपकरणों पर विफल हो जाएगा।
13

45

स्विफ्ट 3 और उसके बाद के संस्करण में

===(या !==)

  • जाँचता है कि क्या मान समान हैं (दोनों समान मेमोरी पते पर इंगित करते हैं)
  • संदर्भ प्रकारों की तुलना करना ।
  • जैसे ==ओब्ज-सी (सूचक समानता) में।

==(या !=)

  • जाँचता है कि क्या मान समान हैं
  • मूल्य प्रकारों की तुलना करना ।
  • isEqual:ओब्ज-सी व्यवहार में डिफ़ॉल्ट की तरह ।

यहाँ मैं तीन उदाहरणों की तुलना करता हूं (वर्ग एक संदर्भ प्रकार है)

class Person {}

let person = Person()
let person2 = person
let person3 = Person()

person === person2 // true
person === person3 // false

आप isEqual:स्विफ्ट में ओवरराइड भी कर सकते हैं :override func isEqual(_ object: Any?) -> Bool {}
थॉमस इलियट

37

स्विफ्ट के साथ सूक्ष्मताएं हैं ===जो केवल सूचक अंकगणित से परे जाती हैं। ऑब्जेक्टिव-सी में आप किसी भी दो पॉइंटर्स (यानी NSObject *) की तुलना करने में सक्षम थे== अब स्विफ्ट में यह सच नहीं है क्योंकि संकलन के दौरान प्रकार बहुत अधिक भूमिका निभाते हैं।

एक खेल का मैदान आपको देगा

1 === 2                    // false
1 === 1                    // true
let one = 1                // 1
1 === one                  // compile error: Type 'Int' does not conform to protocol 'AnyObject'
1 === (one as AnyObject)   // true (surprisingly (to me at least))

तार के साथ हमें इसकी आदत डालनी होगी:

var st = "123"                                 // "123"
var ns = (st as NSString)                      // "123"
st == ns                                       // true, content equality
st === ns                                      // compile error
ns === (st as NSString)                        // false, new struct
ns === (st as AnyObject)                       // false, new struct
(st as NSString) === (st as NSString)          // false, new structs, bridging is not "free" (as in "lunch")
NSString(string:st) === NSString(string:st)    // false, new structs
var st1 = NSString(string:st)                  // "123"
var st2 = st1                                  // "123"
st1 === st2                                    // true
var st3 = (st as NSString)                     // "123"
st1 === st3                                    // false
(st as AnyObject) === (st as AnyObject)        // false

लेकिन फिर आप निम्नानुसार भी मज़े कर सकते हैं:

var st4 = st             // "123"
st4 == st                // true
st4 += "5"               // "1235"
st4 == st                // false, not quite a reference, copy on write semantics

मुझे यकीन है कि आप बहुत अधिक हास्यास्पद मामलों के बारे में सोच सकते हैं :-)

स्विफ्ट 3 के लिए अपडेट (जैसा कि जेकब ट्रोहला की टिप्पणी से सुझाया गया है)

1===2                                    // Compiler error: binary operator '===' cannot be applied to two 'Int' operands
(1 as AnyObject) === (2 as AnyObject)    // false
let two = 2
(2 as AnyObject) === (two as AnyObject)  // false (rather unpleasant)
(2 as AnyObject) === (2 as AnyObject)    // false (this makes it clear that there are new objects being generated)

यह थोड़ा और अधिक सुसंगत दिखता है Type 'Int' does not conform to protocol 'AnyObject', हालाँकि हम तब मिलते हैं

type(of:(1 as AnyObject))                // _SwiftTypePreservingNSNumber.Type

लेकिन स्पष्ट रूपांतरण स्पष्ट करता है कि कुछ चल रहा हो सकता है। स्ट्रिंग-साइड पर चीजें तब NSStringभी उपलब्ध रहेंगी जब तक हम import Cocoa। फिर हमारे पास होगा

var st = "123"                                 // "123"
var ns = (st as NSString)                      // "123"
st == ns                                       // Compile error with Fixit: 'NSString' is not implicitly convertible to 'String'; did you mean to use 'as' to explicitly convert?
st == ns as String                             // true, content equality
st === ns                                      // compile error: binary operator '===' cannot be applied to operands of type 'String' and 'NSString'
ns === (st as NSString)                        // false, new struct
ns === (st as AnyObject)                       // false, new struct
(st as NSString) === (st as NSString)          // false, new structs, bridging is not "free" (as in "lunch")
NSString(string:st) === NSString(string:st)    // false, new objects
var st1 = NSString(string:st)                  // "123"
var st2 = st1                                  // "123"
st1 === st2                                    // true
var st3 = (st as NSString)                     // "123"
st1 === st3                                    // false
(st as AnyObject) === (st as AnyObject)        // false

यह अभी भी दो स्ट्रिंग वर्गों को भ्रमित कर रहा है, लेकिन निहित रूपांतरण को छोड़ने से शायद यह थोड़ा अधिक स्पष्ट हो जाएगा।


2
===तुलना करने के लिए आप ऑपरेटर का उपयोग नहीं कर सकते Ints। स्विफ्ट 3 में नहीं
जैकब ट्रहला Sw

जब भी आप कहते हैं कि एक "नई संरचना" बनाई जा रही है, जो वास्तव में हो रहा है वह एक नई वस्तु है (एक वर्ग प्रकार की) बनाई जा रही है। ===मानों के प्रकारों के लिए अर्थहीन है क्योंकि वे मूल्य प्रकार हैं। विशेष रूप से, आपको तीन प्रकारों को ध्यान में रखने की आवश्यकता है: शाब्दिक प्रकार, जैसे कि 1 या "फू", जो एक चर के लिए बाध्य नहीं है और आम तौर पर केवल संकलन को प्रभावित करता है क्योंकि आप आमतौर पर रनटाइम के दौरान उनके साथ सौदा नहीं करते हैं; संरचना प्रकार जैसे कि Intऔर Stringजो आपको मिलते हैं जब आप एक चर को शाब्दिक रूप से असाइन करते हैं, और जैसे AnyObjectऔर NSString
नागार्जुन

12

उदाहरण के लिए, यदि आप एक वर्ग के दो उदाहरण बनाते हैं जैसे myClass:

var inst1 = myClass()
var inst2 = myClass()

आप उन उदाहरणों की तुलना कर सकते हैं,

if inst1 === inst2

उद्धृत:

जो आप परीक्षण करने के लिए उपयोग करते हैं कि क्या दो वस्तु संदर्भ दोनों एक ही वस्तु उदाहरण को संदर्भित करते हैं।

इसके अंश: Apple Inc. "स्विफ्ट प्रोग्रामिंग लैंग्वेज।" iBooks। https://itun.es/sk/jEUH0.l


11

स्विफ्ट में हमारे पास === सिंबल है जिसका अर्थ है कि दोनों वस्तुएं एक ही संदर्भ समान पते की बात कर रही हैं

class SomeClass {
var a: Int;

init(_ a: Int) {
    self.a = a
}

}

var someClass1 = SomeClass(4)
var someClass2 = SomeClass(4)
someClass1 === someClass2 // false
someClass2 = someClass1
someClass1 === someClass2 // true

4

बस एक मामूली योगदान से संबंधित है Anyवस्तु ।

मैं चारों ओर इकाई परीक्षणों के साथ काम कर रहा था NotificationCenter, जो उपयोग करता हैAny एक पैरामीटर रूप में करता है जिसे मैं समानता के लिए तुलना करना चाहता था।

हालांकि, चूंकि Anyएक समानता ऑपरेशन में उपयोग नहीं किया जा सकता है, इसलिए इसे बदलना आवश्यक था। अंततः, मैं निम्नलिखित दृष्टिकोण पर आ गया, जिसने मुझे अपनी विशिष्ट स्थिति में समानता प्राप्त करने की अनुमति दी, यहाँ एक सरल उदाहरण के साथ दिखाया गया है:

func compareTwoAny(a: Any, b: Any) -> Bool {
    return ObjectIdentifier(a as AnyObject) == ObjectIdentifier(b as AnyObject)
}

यह फ़ंक्शन ObjectIdentifier का लाभ उठाता है , जो ऑब्जेक्ट के लिए एक अनूठा पता प्रदान करता है, जिससे मुझे परीक्षण करने की अनुमति मिलती है।

ObjectIdentifierउपरोक्त लिंक पर Apple के बारे में प्रति ध्यान देने वाली एक वस्तु :

स्विफ्ट में, केवल क्लास इंस्टेंसेस और मेटाटाइप्स की विशिष्ट पहचान है। संरचना, एनम, फ़ंक्शन या टुपल्स के लिए पहचान की कोई धारणा नहीं है।


2

==यह जाँचने के लिए उपयोग किया जाता है कि क्या दो चर समान हैं 2 == 2। लेकिन इसके मामले में ===समानता का मतलब है कि यदि दो उदाहरण वर्गों के संदर्भ में एक ही वस्तु उदाहरण का संदर्भ देते हैं तो एक संदर्भ बनाया जाता है जो कई अन्य उदाहरणों द्वारा आयोजित किया जाता है।


1

स्विफ्ट 4: यूनिट टेस्ट का उपयोग करके एक और उदाहरण जो केवल === के साथ काम करता है

नोट: नीचे दिया गया परीक्षण == के साथ विफल है, === के साथ काम करता है

func test_inputTextFields_Delegate_is_ViewControllerUnderTest() {

        //instantiate viewControllerUnderTest from Main storyboard
        let storyboard = UIStoryboard(name: "Main", bundle: nil)
        viewControllerUnderTest = storyboard.instantiateViewController(withIdentifier: "StoryBoardIdentifier") as! ViewControllerUnderTest 
        let _ = viewControllerUnderTest.view

        XCTAssertTrue(viewControllerUnderTest.inputTextField.delegate === viewControllerUnderTest) 
    }

और वर्ग जा रहा है

class ViewControllerUnderTest: UIViewController, UITextFieldDelegate {
    @IBOutlet weak var inputTextField: UITextField!

    override func viewDidLoad() {
        super.viewDidLoad()
        inputTextField.delegate = self
    }
}

यदि आप == का उपयोग करते हैं, तो यूनिट टेस्ट में त्रुटि Binary operator '==' cannot be applied to operands of type 'UITextFieldDelegate?' and 'ViewControllerUnderTest!'

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.