swift - स्विफ्ट भाषा में विस्मयादिबोधक चिह्न का क्या मतलब है?




optional forced-unwrapping (15)

"उदाहरण को खोलने" का क्या अर्थ है? यह जरूरी क्यों है?

जहां तक ​​मैं काम कर सकता हूं (यह मेरे लिए भी बहुत नया है) ...

शब्द "लपेटा" का तात्पर्य है कि हमें एक वैकल्पिक चर के बारे में सोचना चाहिए , जो कि चमकदार पेपर में लपेटा गया है, जो (उदास!) खाली हो सकता है

जब "लपेटा", वैकल्पिक चर का मान दो संभावित मानों (एक बूलियन की तरह थोड़ा) के साथ एक enum है। यह enum वर्णन करता है कि चर वैल्यू ( Some(T) ) है, या नहीं ( None )।

यदि कोई मूल्य है, तो यह चर को "अनचाहे" करके प्राप्त किया जा सकता है ( Some(T) से T प्राप्त करना)।

john!.apartment = number73 कैसे है john!.apartment = number73 अलग है? (भावानूदित)

यदि आप एक वैकल्पिक चर का नाम लिखते हैं (उदाहरण के लिए पाठ john , बिना ! ), यह "लपेटा" enum (कुछ / कोई नहीं) को संदर्भित करता है, न कि मूल्य स्वयं (टी)। तो john Person उदाहरण नहीं है, और इसमें कोई apartment सदस्य नहीं है:

john.apartment
// 'Person?' does not have a member named 'apartment'

वास्तविक Person मूल्य को विभिन्न तरीकों से हटाया जा सकता है:

  • "मजबूर करने के लिए मजबूर": john! (यदि यह मौजूद है तो Person मान देता है, रनटाइम त्रुटि अगर यह शून्य है)
  • "वैकल्पिक बाध्यकारी": if let p = john { println(p) } (यदि मूल्य मौजूद है तो println निष्पादित करता है)
  • "वैकल्पिक चेनिंग": john?.learnAboutSwift() (यदि मान मौजूद है तो इस john?.learnAboutSwift() -अप विधि को निष्पादित करता है)

मुझे लगता है कि आप नायल मामले में क्या होना चाहिए, और यह कितना संभव है, इस पर निर्भर करता है कि आप अनचाहे करने के इन तरीकों में से एक चुनते हैं। यह भाषा डिज़ाइन शून्य मामले को स्पष्ट रूप से संभालने के लिए मजबूर करता है, जो मुझे लगता है कि ओब्जे-सी पर सुरक्षा में सुधार होता है (जहां शून्य मामले को संभालना आसान है)।

अपडेट करें :

"स्पष्ट रूप से अनचाहे विकल्प" घोषित करने के लिए विस्मयादिबोधक चिह्न वाक्यविन्यास में भी प्रयोग किया जाता है।

उदाहरणों में अब तक, john वैरिएबल को var john:Person? रूप में घोषित किया गया है var john:Person? , और यह एक वैकल्पिक है। यदि आप उस चर के वास्तविक मान चाहते हैं, तो आपको ऊपर दिए गए तीन तरीकों में से एक का उपयोग करके इसे अनदेखा करना होगा।

अगर इसे var john:Person! रूप में घोषित किया गया था var john:Person! इसके बजाए, परिवर्तनीय एक अप्रत्याशित रूप से अनचाहे वैकल्पिक होगा (ऐप्पल की पुस्तक में इस शीर्षक के साथ अनुभाग देखें)। मूल्य तक पहुंचने पर इस तरह के परिवर्तनीय को खोलने की कोई आवश्यकता नहीं है, और john को अतिरिक्त वाक्यविन्यास के बिना उपयोग किया जा सकता है। लेकिन ऐप्पल की किताब कहती है:

बाद में अवांछित विकल्प का उपयोग नहीं किया जाना चाहिए जब एक चर के बाद बिंदु पर एक चर बनने की संभावना है। यदि आप एक चर के जीवनकाल के दौरान एक शून्य मान की जांच करने की आवश्यकता है तो हमेशा एक सामान्य वैकल्पिक प्रकार का उपयोग करें।

अद्यतन 2 :

माइक ऐश द्वारा " दिलचस्प स्विफ्ट फीचर्स " लेख वैकल्पिक प्रकारों के लिए कुछ प्रेरणा देता है। मुझे लगता है कि यह महान, स्पष्ट लेखन है।

अद्यतन 3 :

विस्मयादिबोधक चिह्न के लिए निहित रूप से अनचाहे वैकल्पिक उपयोग के बारे में एक और उपयोगी लेख: क्रिस एडमसन द्वारा " स्विफ्ट एंड द लास्ट माइल "। लेख में बताया गया है कि यह ऐप्पल द्वारा उनके व्यावहारिक उपाय है जो उनके उद्देश्य-सी ढांचे द्वारा उपयोग किए जाने वाले प्रकारों की घोषणा करने के लिए प्रयुक्त होता है जिनमें शून्य हो सकती है। वैकल्पिक प्रकार के रूप में घोषित करना (उपयोग करना ? ) या निहित रूप से अनचाहे (उपयोग करना ! ) "सुरक्षा और सुविधा के बीच एक व्यापार है"। लेख में दिए गए उदाहरणों में, ऐप्पल ने प्रकारों को स्पष्ट रूप से अनचाहे के रूप में घोषित करना चुना है, जिससे कॉलिंग कोड अधिक सुविधाजनक है, लेकिन कम सुरक्षित है।

शायद ऐप्पल भविष्य में अपने ढांचे के माध्यम से कंघी कर सकता है, अनिश्चित रूप से अनचाहे ("शायद कभी नहीं") पैरामीटर की अनिश्चितता को हटा सकता है और उन्हें वैकल्पिक रूप से बदल सकता है ("निश्चित रूप से विशेष रूप से [उम्मीदवार, दस्तावेज!] परिस्थितियों में शून्य हो सकता है) या मानक गैर -ऑप्शनल ("कभी शून्य नहीं है") घोषणाएं, उनके उद्देश्य-सी कोड के सटीक व्यवहार के आधार पर।

स्विफ्ट प्रोग्रामिंग भाषा गाइड में निम्नलिखित उदाहरण हैं:

class Person {
    let name: String
    init(name: String) { self.name = name }
    var apartment: Apartment?
    deinit { println("\(name) is being deinitialized") }
}

class Apartment {
    let number: Int
    init(number: Int) { self.number = number }
    var tenant: Person?
    deinit { println("Apartment #\(number) is being deinitialized") }
}

var john: Person?
var number73: Apartment?

john = Person(name: "John Appleseed")
number73 = Apartment(number: 73)

//From Apple's “The Swift Programming Language” guide (https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/AutomaticReferenceCounting.html)

फिर जब व्यक्ति को अपार्टमेंट सौंपा जाता है, तो वे "उदाहरण को खोलने" के लिए विस्मयादिबोधक बिंदु का उपयोग करते हैं:

john!.apartment = number73

"उदाहरण को खोलने" का क्या अर्थ है? यह जरूरी क्यों है? यह केवल निम्नलिखित करने से अलग कैसे है:

john.apartment = number73

मैं स्विफ्ट भाषा के लिए बहुत नया हूँ। बस मूल बातें पाने की कोशिश कर रहा है।


अद्यतन करें:
उस पहेली का बड़ा टुकड़ा जिसे मैं याद कर रहा था (सीधे जवाब में नहीं बताया गया - कम से कम इस समय लिखने के समय नहीं) यह है कि जब आप निम्न कार्य करते हैं:

var john: Person?

इसका मतलब यह नहीं है कि " john प्रकार का Person और यह शून्य हो सकता है", जैसा कि मैंने मूल रूप से सोचा था। मैं बस Person और Person? गलत समझ रहा था Person? पूरी तरह से अलग प्रकार हैं। एक बार मैंने इसे पकड़ लिया, तो बाकी सब ? , ! पागलपन, और नीचे दिए गए महान उत्तरों, बहुत अधिक समझ में आया।


इस मामले में...

var जॉन: व्यक्ति!

इसका मतलब है कि शुरुआत में जॉन के पास शून्य मूल्य होगा, यह सेट हो जाएगा और एक बार सेट फिर से शून्य-नेतृत्व नहीं होगा। इसलिए सुविधा के लिए मैं वैकल्पिक var तक पहुंचने के लिए आसान वाक्यविन्यास का उपयोग कर सकता हूं क्योंकि यह एक "लागू रूप से अनचाहे वैकल्पिक" है


उद्देश्य सी चर के बिना 'शून्य' के बराबर थे ('शून्य' मानों को 0 और झूठी के समान उपयोग करना भी संभव था), इसलिए सशर्त बयानों में चर का उपयोग करना संभव था (मान वाले वैरिएबल 'TRUE' के समान हैं 'और बिना किसी मूल्य वाले लोग' गलत 'के बराबर थे)।

स्विफ्ट 'वैकल्पिक मूल्य' प्रदान करके प्रकार की सुरक्षा प्रदान करता है। यानी यह विभिन्न प्रकार के चर निर्दिष्ट करने से गठित त्रुटियों को रोकता है।

तो स्विफ्ट में, सशर्त बयान पर केवल बुलियन प्रदान किए जा सकते हैं।

var hw = "Hello World"

यहां, भले ही 'hw' एक स्ट्रिंग है, इसका उपयोग किसी उद्देश्य में सी के रूप में नहीं किया जा सकता है।

//This is an error

if hw

 {..}

इसके लिए इसे बनाने की जरूरत है,

var nhw : String? = "Hello World"

//This is correct

if nhw

 {..}

एक वैकल्पिक चर में एक मान हो सकता है या नहीं हो सकता है

मामला 1: var myVar:String? = "Something" var myVar:String? = "Something"

मामला 2: var myVar:String? = nil var myVar:String? = nil

अब अगर आप myVar से पूछते हैं !, आप संकलक को 1 मामले में एक मूल्य वापस करने के लिए कह रहे हैं, यह "Something"

2 मामले में यह दुर्घटनाग्रस्त हो जाएगा।

मतलब! चिह्न संकलक को एक मूल्य वापस करने के लिए मजबूर करेगा, भले ही वह वहां न हो। यही कारण है कि फोर्स Unwrapping नाम।


जॉन एक वैकल्पिक व्यक्ति है, जिसका अर्थ है कि यह मूल्य रख सकता है या शून्य हो सकता है।

john.apartment = number73

यदि जॉन वैकल्पिक नहीं है तो प्रयोग किया जाता है। चूंकि जॉन कभी शून्य नहीं है, हम सुनिश्चित कर सकते हैं कि यह अपार्टमेंट को शून्य मूल्य पर नहीं बुलाएगा। जबकि

john!.apartment = number73

संकलक का वादा करता है कि जॉन शून्य नहीं है, फिर जॉन के मूल्य प्राप्त करने और जॉन की अपार्टमेंट संपत्ति तक पहुंचने के लिए वैकल्पिक को अनचाहे करता है। अगर आप जानते हैं कि जॉन शून्य नहीं है तो इसका इस्तेमाल करें। यदि आप इसे शून्य विकल्प पर कॉल करते हैं, तो आपको रनटाइम त्रुटि मिल जाएगी।

प्रलेखन में इसका उपयोग करने के लिए एक अच्छा उदाहरण शामिल है जहां कनवर्ट नम्बर वैकल्पिक है।

if convertedNumber {
    println("\(possibleNumber) has an integer value of \(convertedNumber!)")
} else {
    println("\(possibleNumber) could not be converted to an integer")
}

टी एल; डॉ

स्विफ्ट भाषा में विस्मयादिबोधक चिह्न का क्या मतलब है?

विस्मयादिबोधक चिह्न प्रभावी रूप से कहता है, "मुझे पता है कि इस वैकल्पिक के पास निश्चित रूप से मूल्य है; कृपया इसका इस्तेमाल करें। "इसे वैकल्पिक मूल्य के मजबूर अनचाहे के रूप में जाना जाता है:

उदाहरण

let possibleString: String? = "An optional string."
print(possibleString!) // requires an exclamation mark to access its value
// prints "An optional string."

let assumedString: String! = "An implicitly unwrapped optional string."
print(assumedString)  // no exclamation mark is needed to access its value
// prints "An implicitly unwrapped optional string."

स्रोत: https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/TheBasics.html#//apple_ref/doc/uid/TP40014097-CH5-XID_399


द! किसी ऑब्जेक्ट के अंत में यह कहता है कि ऑब्जेक्ट एक वैकल्पिक है और अगर यह अन्यथा शून्य हो सकता है तो इसे खोलने के लिए। यह अक्सर त्रुटियों को फँसाने के लिए प्रयोग किया जाता है जो अन्यथा कार्यक्रम को दुर्घटनाग्रस्त कर देते हैं।


पूरी कहानी स्विफ्ट नामक वैकल्पिक वार्स के साथ शुरू होती है। ये वे वर्ण हैं जिनके पास मूल्य हो सकता है या उनके पास मूल्य नहीं हो सकता है। सामान्य तेज़ी से हमें एक वैरिएबल का उपयोग करने की अनुमति नहीं देता है जिसे प्रारंभ नहीं किया जाता है, क्योंकि इससे क्रैश या अप्रत्याशित कारण हो सकते हैं और बैकडोर्ड्स के लिए प्लेसहोल्डर भी हो सकता है। इस प्रकार एक वेरिएबल घोषित करने के लिए जिसका मूल्य प्रारंभ में निर्धारित नहीं है, हम '?' का उपयोग करते हैं। जब इस तरह के एक चर को घोषित किया जाता है, इसे किसी अभिव्यक्ति के हिस्से के रूप में उपयोग करने के लिए किसी को उपयोग से पहले उन्हें खोलना होता है, तो अनचाहे एक ऑपरेशन होता है जिसके माध्यम से एक चर के मूल्य की खोज की जाती है यह वस्तुओं पर लागू होती है। अगर आप उनका उपयोग करने का प्रयास करते हैं तो अनचाहे किए बिना आप समय त्रुटि संकलित करेंगे। एक वेरिएबल को अनचाहे करने के लिए जो एक वैकल्पिक var है, विस्मयादिबोधक चिह्न "!" प्रयोग किया जाता है।

अब ऐसे समय होते हैं जब आप जानते हैं कि ऐसे वैकल्पिक चर को उदाहरण के लिए सिस्टम या आपके स्वयं के कार्यक्रम के लिए मूल्यों को असाइन किया जाएगा, लेकिन कुछ समय बाद, उदाहरण के लिए यूआई आउटलेट, ऐसी स्थिति में एक वैकल्पिक चर घोषित करने के बजाय एक प्रश्न चिह्न "?" हम प्रयोग करते हैं "!"।

इस प्रकार सिस्टम जानता है कि यह चर जो "!" के साथ घोषित किया गया है अभी वैकल्पिक है और इसका कोई मूल्य नहीं है लेकिन बाद में इसके जीवनकाल में एक मूल्य प्राप्त होगा।

इस प्रकार विस्मयादिबोधक चिह्न में दो अलग-अलग उपयोग होते हैं, 1. एक वेरिएबल घोषित करने के लिए जो वैकल्पिक होगा और निश्चित रूप से बाद में मूल्य प्राप्त करेगा 2. अभिव्यक्ति में इसका उपयोग करने से पहले एक वैकल्पिक चर को खोलने के लिए।

ऊपर दिए गए विवरण तकनीकी सामान से बहुत अधिक बचाते हैं, मुझे उम्मीद है।


यदि आप सी # से परिचित हैं, तो यह शून्य प्रकारों की तरह है जिन्हें एक प्रश्न चिह्न का उपयोग करके भी घोषित किया जाता है:

Person? thisPerson;

और इस मामले में विस्मयादिबोधक चिह्न इस तरह के शून्य प्रकार की वैल्यू प्रॉपर्टी तक पहुंचने के बराबर है:

thisPerson.Value

यदि आप सी-पारिवारिक भाषा से आए हैं, तो आप सोचेंगे कि "टाइप एक्स के ऑब्जेक्ट के पॉइंटर जो मेमोरी एड्रेस 0 (एनयूएलएल) हो सकता है", और यदि आप गतिशील रूप से टाइप की गई भाषा से आ रहे हैं तो आप होंगे सोच रहा है "ऑब्जेक्ट जो शायद एक्स प्रकार का है लेकिन शायद अपरिभाषित प्रकार का हो सकता है"। इनमें से कोई भी वास्तव में सही नहीं है, हालांकि एक चौराहे के रास्ते में पहला व्यक्ति करीब है।

जिस तरह से आपको इसके बारे में सोचना चाहिए, जैसे कि यह एक वस्तु है जैसे:

struct Optional<T> {
   var isNil:Boolean
   var realObject:T
}

जब आप foo == nil साथ अपने वैकल्पिक मान का परीक्षण कर रहे हैं तो यह वास्तव में foo.isNil लौट foo.isNil , और जब आप foo! कहते हैं foo! यह foo.isNil == false कि एक दावा के साथ foo.realObject लौट रहा है। यह ध्यान रखना महत्वपूर्ण है क्योंकि यदि आप foo! करते हैं तो वास्तव में foo वास्तव में शून्य है foo! , यह एक रनटाइम त्रुटि है, इसलिए आमतौर पर आप एक सशर्त चलो का उपयोग करना चाहते हैं, जब तक कि आप सुनिश्चित न हों कि मान शून्य नहीं होगा। इस तरह की चालबाजी का मतलब है कि अगर आप हर जगह मूल्य शून्य हैं तो परीक्षण करने के लिए मजबूर किए बिना भाषा को मजबूती से टाइप किया जा सकता है।

व्यवहार में, यह वास्तव में ऐसा व्यवहार नहीं करता है क्योंकि काम संकलक द्वारा किया जाता है। एक उच्च स्तर पर एक प्रकार का Foo? जो Foo से अलग है, और यह उन फिक्सेस को रोकता है जो Foo को शून्य मान प्राप्त करने से स्वीकार करते हैं, लेकिन कम स्तर पर वैकल्पिक मान वास्तविक वस्तु नहीं है क्योंकि इसमें कोई गुण या विधियां नहीं हैं; यह संभावना है कि वास्तव में यह एक सूचक है जो न्यूल (0) द्वारा उचित परीक्षण के साथ बल-अनचाहे होने पर हो सकता है।

वहां एक अन्य स्थिति जिसमें आप एक विस्मयादिबोधक चिह्न देखेंगे, जैसा कि:

func foo(bar: String!) {
    print(bar)
}

यह एक मजबूर अनचाहे के साथ एक वैकल्पिक स्वीकार करने के बराबर है, यानी:

func foo(bar: String?) {
    print(bar!)
}

आप इसका उपयोग एक विधि के लिए कर सकते हैं जो तकनीकी रूप से वैकल्पिक मान स्वीकार करता है लेकिन यदि यह शून्य है तो रनटाइम त्रुटि होगी। स्विफ्ट के वर्तमान संस्करण में यह स्पष्ट रूप से नॉन-नॉन-एनिल दावे को छोड़ देता है ताकि आपके पास निम्न स्तर की त्रुटि हो। आम तौर पर एक अच्छा विचार नहीं है, लेकिन यह किसी अन्य भाषा से कोड परिवर्तित करते समय उपयोगी हो सकता है।


यहाँ कुछ उदाहरण हैं:

var name:String = "Hello World"
var word:String?

जहां word एक वैकल्पिक मूल्य है। इसका मतलब है कि इसमें कोई मान हो सकता है या नहीं।

word = name 

यहां name का मूल्य है ताकि हम इसे असाइन कर सकें

var cow:String = nil
var dog:String!

जहां dog को मजबूती से खोल दिया जाता है, इसका मतलब है कि इसमें एक मूल्य होना चाहिए

dog = cow

एप्लिकेशन क्रैश हो जाएगा क्योंकि हम अनचाहे करने के लिए nil निर्दिष्ट कर रहे हैं


यहां मुझे लगता है कि अंतर क्या है:

var john: Person?

मतलब जॉन शून्य हो सकता है

john?.apartment = number73

कंपाइलर इस लाइन की व्याख्या इस प्रकार करेगा:

if john != nil {
    john.apartment = number73
}

जबकि

john!.apartment = number73

कंपाइलर इस लाइन को आसानी से समझेंगे:

john.apartment = number73

इसलिए, उपयोग कर! अगर कथन को अनदेखा कर देगा, और इसे तेजी से चलाएगा, लेकिन यदि जॉन शून्य है, तो रनटाइम त्रुटि होगी।

तो यहां लपेटें इसका मतलब यह नहीं है कि यह स्मृति लपेटा गया है, लेकिन इसका मतलब है कि यह कोड लपेटा गया है, इस मामले में यह एक कथन के साथ लपेटा गया है, और क्योंकि ऐप्पल रनटाइम में प्रदर्शन पर बारीकी से ध्यान देता है, तो वे आपको एक रास्ता देना चाहते हैं अपने ऐप को सर्वोत्तम संभव प्रदर्शन के साथ चलाएं।

अद्यतन करें:

4 साल बाद इस जवाब पर वापस आना, क्योंकि मुझे स्टैक ओवरफ्लो में इससे उच्चतम प्रतिष्ठा मिली है :) मैंने उस समय अनचाहे होने का अर्थ थोड़ा सा गलत समझा। अब 4 वर्षों के बाद मेरा मानना ​​है कि यहां अनचाहे होने का अर्थ कोड को अपने मूल कॉम्पैक्ट फॉर्म से विस्तारित करना है। इसके अलावा इसका मतलब उस वस्तु के चारों ओर अस्पष्टता को दूर करना है, क्योंकि हम निश्चित रूप से परिभाषित नहीं हैं कि यह शून्य है या नहीं। उपरोक्त एशले के जवाब की तरह, इसके बारे में एक उपस्थिति के रूप में सोचें जिसमें इसमें कुछ भी शामिल नहीं हो सकता है। लेकिन मुझे अभी भी लगता है कि अनैपिंग कोड अनैपिंग है और स्मृति के आधार पर स्मृति आधारित नहीं है।


john एक वैकल्पिक var । तो एक nil मूल्य हो सकता है। यह सुनिश्चित करने के लिए कि मूल्य शून्य उपयोग नहीं है ! var नाम के अंत में।

दस्तावेज से

"एक बार जब आप सुनिश्चित हों कि वैकल्पिक में कोई मान होता है, तो आप वैकल्पिक नाम के अंत में विस्मयादिबोधक चिह्न (!) जोड़कर इसके अंतर्निहित मूल्य तक पहुंच सकते हैं। विस्मयादिबोधक चिह्न प्रभावी रूप से कहता है, "मुझे पता है कि इस वैकल्पिक के पास निश्चित रूप से मूल्य है; कृपया इसका इस्तेमाल करें। "

गैर शून्य मूल्य की जांच करने का एक और तरीका है

    if let j = json {
        // do something with j
    }

सरल शब्दों में

विस्मयादिबोधक चिह्न का उपयोग इंगित करता है कि चर में गैर शून्य मान होना चाहिए (यह शून्य नहीं होगा)


Simple the Optional variable allows nil to be stored.

var str : String? = nil

str = "Data"

To convert Optional to the Specific DataType, We unwrap the variable using the keyword "!"

func get(message : String){
   return
}

get(message : str!)  // Unwapped to pass as String




forced-unwrapping