स्विफ्ट में "अलिखित मूल्य" क्या है?


155

मैं इस ट्यूटोरियल का अनुसरण करके iOS 8 / OSX 10.10 के लिए स्विफ्ट सीख रहा हूं , और " अपरिवर्तित मूल्य " शब्द का उपयोग कई बार किया जाता है, जैसा कि इस पैराग्राफ में ( ऑब्जेक्ट्स और क्लास के तहत ):

वैकल्पिक मूल्यों के साथ काम करते समय, आप लिख सकते हैं? विधियों, गुणों और सदस्यता जैसे संचालन से पहले। यदि मूल्य से पहले? शून्य है, सब कुछ के बाद? को अनदेखा किया जाता है और संपूर्ण अभिव्यक्ति का मूल्य शून्य होता है। अन्यथा, वैकल्पिक मूल्य अपरिवर्तित है , और सब कुछ के बाद? अलिखित मूल्य पर कार्य करता है । दोनों मामलों में, संपूर्ण अभिव्यक्ति का मूल्य एक वैकल्पिक मूल्य है।

let optionalSquare: Square? = Square(sideLength: 2.5, name: "optional square") 
let sideLength = optionalSquare?.sideLength

मुझे यह नहीं मिलता है, और भाग्य के बिना वेब पर खोज की है।

इसका क्या मतलब है?


संपादित करें

सेज़री के उत्तर से, मूल कोड के उत्पादन और अंतिम समाधान (खेल के मैदान पर परीक्षण) के बीच थोड़ा अंतर है:

मूल कोड

मूल कोड

सीज़री का समाधान

सीज़री का समाधान

सुपरक्लास के गुण दूसरे मामले में आउटपुट में दिखाए गए हैं, जबकि पहले मामले में एक खाली वस्तु है।

क्या परिणाम दोनों ही मामलों में समान नहीं है?

संबंधित प्रश्न और एक: स्विफ्ट में एक वैकल्पिक मूल्य क्या है?


1
सीज़री का जवाब हाजिर है। इसके अलावा, iBooks पर मुफ्त में
डैनियल स्टॉर्म

@DanielStormApps यह iBook मेरे प्रश्न में लिंक किए गए ट्यूटोरियल का एक पोर्टेबल संस्करण है :)
बिग जूड

जवाबों:


289

सबसे पहले, आपको यह समझना होगा कि एक वैकल्पिक प्रकार क्या है। एक वैकल्पिक प्रकार मूल रूप से इसका मतलब है कि चर हो सकता है nil

उदाहरण:

var canBeNil : Int? = 4
canBeNil = nil

प्रश्न चिह्न इस तथ्य को इंगित करता है कि canBeNilहो सकता है nil

यह काम नहीं करेगा:

var cantBeNil : Int = 4
cantBeNil = nil // can't do this

अपने वैरिएबल से मान प्राप्त करने के लिए यदि यह वैकल्पिक है, तो आपको इसे खोलना होगा । इसका मतलब सिर्फ अंत में एक विस्मयादिबोधक बिंदु डालना है।

var canBeNil : Int? = 4
println(canBeNil!)

आपका कोड इस तरह दिखना चाहिए:

let optionalSquare: Square? = Square(sideLength: 2.5, name: "optional square") 
let sideLength = optionalSquare!.sideLength

एक संदेश:

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

उदाहरण:

var canBeNil : Int! = 4
print(canBeNil) // no unwrapping needed

तो अपने कोड को ठीक करने का एक वैकल्पिक तरीका है:

let optionalSquare: Square! = Square(sideLength: 2.5, name: "optional square") 
let sideLength = optionalSquare.sideLength

संपादित करें:

जो अंतर आप देख रहे हैं वह वास्तव में इस तथ्य का लक्षण है कि वैकल्पिक मूल्य लिपटा हुआ है । इसके ऊपर एक और परत होती है। Unwrapped क्योंकि यह अच्छी तरह से है, unwrapped संस्करण सिर्फ सीधे वस्तु को दर्शाता है।

एक त्वरित खेल का मैदान तुलना:

खेल का मैदान

पहले और दूसरे मामलों में, ऑब्जेक्ट स्वचालित रूप से अलिखित नहीं किया जा रहा है, इसलिए आप दो "परतें" ( {{...}}) देखते हैं , जबकि तीसरे मामले में, आप केवल एक परत ( {...}) देखते हैं क्योंकि ऑब्जेक्ट स्वचालित रूप से अलिखित हो रहा है।

पहले मामले और दूसरे दो मामलों के बीच का अंतर यह है कि दूसरे दो मामले आपको रनटाइम त्रुटि देंगे यदि optionalSquareसेट किया गया है nil। पहले मामले में वाक्य रचना का उपयोग करना, आप कुछ इस तरह कर सकते हैं:

if let sideLength = optionalSquare?.sideLength {
    println("sideLength is not nil")
} else {
    println("sidelength is nil")
}

1
स्पष्ट स्पष्टीकरण के लिए धन्यवाद! मेरे प्रश्न में शामिल कोड को Apple के ट्यूटोरियल (प्रश्न में लिंक) से उद्धृत किया गया है, और मुझे लगता है कि यह काम करना चाहिए (और यह करता है)। हालाँकि, आपका अंतिम समाधान और मूल एक ही परिणाम अलग-अलग होता है (मेरे संपादन देखें)। कोई सोच?
बिग जू

2
ठंडा। महान व्याख्या। मैं अभी भी उलझन में हूँ, हालांकि। मैं वैकल्पिक मूल्य का उपयोग क्यों करना चाहूंगा? यह कब उपयोगी है? Apple ने यह व्यवहार और वाक्य रचना क्यों बनाया?
टॉड लेहमन

1
यह विशेष रूप से प्रासंगिक है जब यह वर्ग गुणों की बात आती है। स्विफ्ट को init()क्लास के फंक्शन में इनिशियलाइज़ करने के लिए सभी गैर-वैकल्पिक तरीकों की आवश्यकता होती है । मैं ऐप्पल द्वारा जारी की गई स्विफ्ट पुस्तक में अध्याय "द बेसिक्स" (वैकल्पिक को शामिल करता है), "इनिशियलाइज़ेशन" और "वैकल्पिक चेनिंग" को पढ़ने की सलाह देता हूं।
Cezary Wojcik

2
@ToddLehman Apple ने इसे ज्यादा सुरक्षित कोड लिखने में आपकी मदद करने के लिए बनाया है। उदाहरण के लिए जावा में सभी अशक्त सूचक अपवादों की कल्पना करें क्योंकि एक कार्यक्रम दुर्घटनाग्रस्त हो गया क्योंकि कोई व्यक्ति शून्य की जांच करना भूल गया था। या उद्देश्य-सी पर अजीब व्यवहार क्योंकि आप शून्य की जांच करना भूल गए। वैकल्पिक प्रकार के साथ आप शून्य से निपटना नहीं भूल सकते। संकलक आपको इससे निपटने के लिए मजबूर करता है।
एरिक इंगोह

5
@AdamSmith - जावा बैकग्राउंड से आने वाले, मैं निश्चित रूप से ऑप्शनल के उपयोग को देख सकता हूं ... लेकिन ऑब्जेक्टिव-सी बैकग्राउंड से भी (हाल ही में) आ रहा हूं, मुझे अभी भी इसका उपयोग देखने में परेशानी हो रही है, क्योंकि ऑब्जेक्टिव- सी स्पष्ट रूप से आपको शून्य वस्तुओं पर संदेश भेजने की अनुमति देता है। हम्म। मैं किसी को इनका उदाहरण दिखाते हुए देखना पसंद करूंगा कि कैसे वे कोड को छोटे बनाने में मदद करते हैं और समान कोड की तुलना में सुरक्षित होते हैं जो उनका उपयोग नहीं करता है। मैं यह नहीं कह रहा हूं कि वे उपयोगी नहीं हैं; मैं बस कह रहा हूं कि मुझे अभी तक नहीं मिला "।
टॉड लेहमन

17

मौजूदा सही उत्तर बहुत अच्छा है, लेकिन मैंने पाया कि मेरे लिए इसे पूरी तरह से समझने के लिए, मुझे एक अच्छी सादृश्यता की आवश्यकता थी, क्योंकि यह एक बहुत ही सार और अजीब अवधारणा है।

इसलिए, मुझे सही उत्तर के अलावा एक अलग दृष्टिकोण देकर उन साथी "राइट-ब्रेनडेड" (दृश्य सोच) डेवलपर्स की मदद करने दें। यहाँ एक अच्छा सादृश्य है जिसने मुझे बहुत मदद की।

जन्मदिन का उपहार रैपिंग सादृश्य

वैकल्पिक के बारे में सोचें जैसे कि जन्मदिन प्रस्तुत करता है जो कठोर, कठोर, रंगीन रैपिंग में आते हैं।

आप नहीं जानते कि क्या लपेटने के अंदर कुछ भी है जब तक आप वर्तमान को खोल नहीं देते हैं - शायद अंदर कुछ भी नहीं है! अगर अंदर कुछ है, तो यह अभी तक एक और वर्तमान हो सकता है, जो लपेटा हुआ है, और जिसमें कुछ भी नहीं हो सकता है । आप शायद अंत में 100 नेस्टेड प्रस्तुत भी कर सकते हैं ताकि पता चले कि लपेटने के अलावा कुछ नहीं था ।

यदि वैकल्पिक का मान नहीं है nil, तो अब आपके सामने एक बॉक्स है, जिसमें कुछ है । लेकिन, विशेष रूप से यदि मूल्य स्पष्ट रूप से टाइप नहीं किया गया है और एक चर है और एक पूर्वनिर्धारित स्थिरांक नहीं है, तो आपको अभी भी बॉक्स खोलने की आवश्यकता हो सकती है इससे पहले कि आप बॉक्स में क्या है, जैसे क्या है, या क्या है, इसके बारे में कुछ भी जान सकते हैं । वास्तविक मूल्य है

बॉक्स में क्या है?! समानता

चर को अंजाम देने के बाद भी, आप अभी भी SE7EN में आखिरी दृश्य में ब्रैड पिट की तरह हैं ( चेतावनी : बिगाड़ने वाले और बहुत ही आर-रेटेड बेईमानी और हिंसा), क्योंकि वर्तमान को समाप्त करने के बाद भी, आप निम्न स्थिति में हैं। अब आपके पास है nil, या एक बॉक्स जिसमें कुछ है (लेकिन आप नहीं जानते कि क्या है)।

आप कुछ का प्रकार जान सकते हैं । उदाहरण के लिए, यदि आपने वेरिएबल को टाइप होने के रूप में घोषित किया है [Int:Any?], तो आपको पता होगा कि पूर्णांक सब्सक्राइबर्स के साथ आपके पास एक (संभावित रूप से खाली) डिक्शनरी है, जो किसी भी पुराने प्रकार के लिपटे हुए कंटेंट की उपज देती है।

यही कारण है कि स्विफ्ट में संग्रह प्रकारों (डिक्शनरी और एरेस) के साथ काम करने से बालों के प्रकार हो सकते हैं।

इसका स्पष्ट उदाहरण:

typealias presentType = [Int:Any?]

func wrap(i:Int, gift:Any?) -> presentType? {
    if(i != 0) {
        let box : presentType = [i:wrap(i-1,gift:gift)]
        return box
    }
    else {
        let box = [i:gift]
        return box
    }
}

func getGift() -> String? {
    return "foobar"
}

let f00 = wrap(10,gift:getGift())

//Now we have to unwrap f00, unwrap its entry, then force cast it into the type we hope it is, and then repeat this in nested fashion until we get to the final value.

var b4r = (((((((((((f00![10]! as! [Int:Any?])[9]! as! [Int:Any?])[8]! as! [Int:Any?])[7]! as! [Int:Any?])[6]! as! [Int:Any?])[5]! as! [Int:Any?])[4]! as! [Int:Any?])[3]! as! [Int:Any?])[2]! as! [Int:Any?])[1]! as! [Int:Any?])[0])

//Now we have to DOUBLE UNWRAP the final value (because, remember, getGift returns an optional) AND force cast it to the type we hope it is

let asdf : String = b4r!! as! String

print(asdf)

अच्छा 😊😊 😊😊 😊 😊😊 😊 Sam
SamSol

सादृश्य प्यार! तो, वहाँ एक बेहतर तरीका है तो बक्से खोलना है? अपने कोड उदाहरण में
डेविड टी।

श्रोडिंगर की बिल्ली बॉक्स में है
जैक्सन

मुझे भ्रमित करने के लिए धन्यवाद .... किस तरह का प्रोग्रामर बर्थडे प्रेजेंट देता है जो किसी भी तरह से खाली है? थोड़े का मतलब
०१ पर ०१ at२ एफएल

@Jacksonkr या नहीं।
amsmath

13

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

स्विफ्ट में सभी वैकल्पिकों को ?प्रतीक के साथ सीमांकित किया जाता है। ?जिस प्रकार के विकल्प को आप वैकल्पिक घोषित कर रहे हैं , उसके नाम को निर्धारित करके आप अनिवार्य रूप से इसे उस प्रकार के रूप में नहीं डाल रहे हैं, जिसमें पहले है ?, बल्कि वैकल्पिक प्रकार के रूप में है ।


ध्यान दें: एक चर या प्रकार Intहै नहीं के रूप में ही Int?। वे दो अलग-अलग प्रकार हैं जिन्हें एक दूसरे पर संचालित नहीं किया जा सकता है।


वैकल्पिक का उपयोग करना

var myString: String?

myString = "foobar"

इसका मतलब यह नहीं है कि आप एक प्रकार के साथ काम कर रहे हैं String। इसका मतलब है कि आप एक प्रकार के String?(स्ट्रिंग ऑप्शनल या वैकल्पिक स्ट्रिंग) के साथ काम कर रहे हैं । वास्तव में, जब भी आप प्रयास करें

print(myString)

रनटाइम पर, डिबग कंसोल प्रिंट होगा Optional("foobar")। " Optional()" भाग इंगित करता है कि इस चर का रनटाइम पर कोई मान नहीं हो सकता है, लेकिन अभी ऐसा होता है कि वर्तमान में स्ट्रिंग "फोब्बर" हो सकता है। यह " Optional()" संकेत तब तक बना रहेगा जब तक कि आप वह नहीं करते हैं जिसे वैकल्पिक मान "अलिखित" कहा जाता है।

एक वैकल्पिक का अनावरण करने का अर्थ है कि आप अब उस प्रकार को गैर-वैकल्पिक के रूप में कास्टिंग कर रहे हैं। यह एक नया प्रकार उत्पन्न करेगा और नए गैर-वैकल्पिक प्रकार के लिए उस वैकल्पिक के भीतर रहने वाले मान को असाइन करेगा। इस तरह से आप उस चर पर परिचालन कर सकते हैं क्योंकि यह संकलक द्वारा ठोस मूल्य रखने की गारंटी देता है।


सशर्त unwrapping जांच करेगा कि वैकल्पिक में मूल्य है nilया नहीं। यदि ऐसा नहीं है nil, वहाँ एक नव निर्मित निरंतर परिवर्तनशील है कि मूल्य और आवंटित किया जाएगा हो जाएगा unwrapped गैर वैकल्पिक निरंतर में। और वहां से आप ifब्लॉक में गैर-वैकल्पिक का सुरक्षित रूप से उपयोग कर सकते हैं ।

नोट: आप अपने सशर्त रूप से अपरिवर्तित स्थिर नाम को उसी चर के रूप में दे सकते हैं जिसे आप अलिखित कर रहे हैं।

if let myString = myString {
    print(myString)
    // will print "foobar"
}

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

if let myString = myString {
    print(myString)
    // will print "foobar"
}
else {
    print("No value")
}

जबरन Unwrapping को !"(बैंग") ऑपरेटर के रूप में जाना जाता है जिसे नियोजित करके किया जाता है । यह कम सुरक्षित है लेकिन फिर भी आपके कोड को संकलित करने की अनुमति देता है। हालांकि जब भी आप बैंग ऑपरेटर का उपयोग करते हैं तो आपको 1000% निश्चित होना चाहिए कि आपके चर वास्तव में जबरन अलिखित करने से पहले एक ठोस मूल्य रखते हैं।

var myString: String?

myString = "foobar"

print(myString!)

यह ऊपर पूरी तरह से वैध स्विफ्ट कोड है। यह उस मूल्य को प्रिंट करता है जिसे myString"फोब्बर" के रूप में सेट किया गया था। उपयोगकर्ता foobarकंसोल में मुद्रित होता है और इसके बारे में है। लेकिन मान लेते हैं कि मूल्य कभी निर्धारित नहीं था:

var myString: String?

print(myString!) 

अब हमारे हाथों पर एक अलग स्थिति है। ऑब्जेक्टिव-सी के विपरीत, जब भी किसी विकल्प को जबरन बंद करने का प्रयास किया जाता है, और वैकल्पिक सेट नहीं किया गया है और nilजब आप वैकल्पिक को अनट्रैप करने की कोशिश करते हैं, तो यह देखने के लिए कि आपके एप्लिकेशन के अंदर क्या दुर्घटना होगी।


अनवांटेड w / टाइप कास्टिंग । जैसा कि हमने पहले कहा था कि जब आप unwrappingवैकल्पिक होते हैं तो आप वास्तव में एक गैर-वैकल्पिक प्रकार के लिए कास्टिंग करते हैं, आप गैर-वैकल्पिक को एक अलग प्रकार में भी डाल सकते हैं। उदाहरण के लिए:

var something: Any?

कहीं न कहीं हमारे कोड में वेरिएबल somethingकुछ मूल्य के साथ सेट हो जाएगा। हो सकता है कि हम जेनेरिक का उपयोग कर रहे हों या हो सकता है कि कुछ और तर्क हैं जो इस पर चल रहे हैं कि इससे बदलाव आएगा। इसलिए बाद में हमारे कोड में हम इसका उपयोग करना चाहते हैं somethingलेकिन फिर भी यदि यह एक अलग प्रकार है तो इसका इलाज अलग तरह से किया जा सकता है। इस स्थिति में आप इसे asनिर्धारित करने के लिए कीवर्ड का उपयोग करना चाहेंगे :

नोट: asऑपरेटर है कि आप स्विफ्ट में कैसे टाइप करते हैं।

// Conditionally
if let thing = something as? Int {
    print(thing) // 0
}

// Optionally
let thing = something as? Int
print(thing) // Optional(0)

// Forcibly
let thing = something as! Int
print(thing) // 0, if no exception is raised

दो asखोजशब्दों के बीच अंतर पर ध्यान दें । पहले की तरह जब हमने जबरन एक अलिखित विकल्प का उपयोग किया तो हमने ऐसा करने के लिए !बैंग ऑपरेटर का उपयोग किया । यहां आप एक ही काम करेंगे लेकिन सिर्फ एक गैर-वैकल्पिक के रूप में कास्टिंग करने के बजाय आप इसे भी कास्टिंग कर रहे हैं Int। और यह डाउनकास्ट होने में सक्षम होना चाहिए Int, अन्यथा, जैसे कि बैंग ऑपरेटर का उपयोग करना जब मूल्य nilआपका एप्लिकेशन क्रैश हो जाएगा।

और किसी प्रकार या गणितीय ऑपरेशन में इन चर का उपयोग करने के लिए उन्हें ऐसा करने के लिए अलिखित होना चाहिए।

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

फिर भी के साथ कास्टिंग as!आपके कोड को संकलित करने की अनुमति देगा। के साथ कास्टिंग करके as?एक अलग कहानी है। वास्तव में, as?अपने सभी Intको एक साथ पूरी तरह से अलग डेटा प्रकार के रूप में घोषित करता है ।

अब यह है Optional(0)

और अगर आपने कभी अपना होमवर्क कुछ ऐसा लिखने की कोशिश की

1 + Optional(1) = 2

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

सुरक्षा पहले बच्चे।


वैकल्पिक प्रकारों की अच्छी व्याख्या। मेरे लिए स्पष्ट चीजों में मदद की।
Tobe_Sta

0

'?' मतलब वैकल्पिक जंजीर अभिव्यक्ति

'!' का मतलब है बल-मूल्य
यहां छवि विवरण दर्ज करें

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