2017-07-12 32 views
7

मैं स्विफ्ट में एक चर घोषित करने के लिए काफी रोचक इन अलग अलग तरीकों से पाया:स्विफ्ट में एक चर कैसे घोषित करें?

// METHOD 1 
var dogName: String = "Charlie" 

// METHOD 2 
var dogName: String { 
    return "Charlie" 
} 

// METHOD 3 
let dogName = { 
    return "Charlie" 
} 

// METHOD 4 
var dogName: String = { 
    return "Charlie" 
}() 

जाहिर विधि 3 घोषणा एक लेट और हम अंतर जाना जाता है; लेकिन क्यों स्विफ्ट विधि 4 की अनुमति देता है?

इन चार तरीकों के बीच क्या अंतर है?

मैं विधि 2 और 4 के बीच विशेष रूप से उलझन में हूं। इसके अलावा विधि 3 विधि 4 की तुलना में अंतिम ब्रैकेट क्यों खो देता है?

उत्तर

5

विधि 1 एक स्ट्रिंग के लिए एक मानक चर घोषणा है।> स्ट्रिंग - यह एक सेटर और एक गेटर

var dogName: String = "Charlie" 

print(dogName) -> "Charlie" 
dogName = "Rex" // Valid 

विधि 2 प्रकार स्ट्रिंग की एक गणना संपत्ति है और केवल पढ़ने के लिए है

var dogName: String { 
    return "Charlie" 
} 

print(dogName) -> "Charlie" 
dogName = "Rex" // Invalid as property is read-only 

विधि 3, रीड-ओनली प्रकार() की संपत्ति है है , इसलिए मूल रूप से एक लैम्ब्डा समारोह।

let dogName = { 
    return "Charlie" 
} 

print(dogName) -> "(Function)" 
print(dogName()) -> "Charlie" 
dogName = "Rex" // Invalid as property is read-only 

विधि 4 एक बंद है जिसे युक्त ऑब्जेक्ट प्रारंभ होने पर निष्पादित किया जाएगा। यह एक var है के रूप में आप एक और मूल्य

var dogName: String = { 
    return "Charlie" 
}() 

print(dogName) -> "Charlie" 
dogName = "Rex" // Valid 

कहा जा रहा है के साथ यह जगह ले सकता है के रूप में विधि 4 को बंद करने की है, तो आप उस में अन्य आदेश पर अमल कर सकते हैं। यहाँ एक उदाहरण है जहाँ आप एक UILabel आरंभ करने के लिए इस संरचना का उपयोग कर सकते है:

var dogNameLabel: UILabel = { 
    let label = UILabel(frame: CGRect(x: 0, y: 0, width: 10, height: 10)) 
    label.text = "Charlie" 
    return label 
}() 
+1

वैसे आप कि वास्तव में विधि के बारे में सही 4. बंद वस्तु है, जहां संपत्ति घोषित किया जाता है और जब इस तक पहुंच नहीं की आरंभीकरण पर निष्पादित किया जाएगा नहीं हैं। इस प्रकार, यह उस बंद होने के परिणाम से असाइन किए गए डिफ़ॉल्ट संपत्ति मान की तरह है। लेकिन आप सही हैं, आप बाद में इसे किसी और चीज़ से बदल सकते हैं। –

+1

@OlegDanu आप पूरी तरह से सही हैं, मैंने तदनुसार जवाब अपडेट किया। धन्यवाद! – Thomas

+1

गणना गुण हमेशा पढ़ने-योग्य नहीं होते हैं, बीटीडब्ल्यू। आप उन्हें लिखने के लिए गणना की गई संपत्तियों पर 'get' और' set' परिभाषित कर सकते हैं। जब ऊपर दिखाए गए अनुसार घोषित किया गया, हालांकि, वे निश्चित रूप से केवल एक गेटर है, जो प्रभावी रूप से उन्हें केवल पढ़ने के लिए बनाता है। Https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Properties.html#//apple_ref/doc/uid/TP40014097-CH14-ID259 –

1

विधि 1 काफी स्पष्ट है।

विधि 2 में आपने जो किया है, क्या आपने दिए गए चर के लिए गेटर परिभाषित किया है।

विधि 3 में dogName का प्रकार () -> String है और String नहीं है। आपने जो नाम शुरू किया वह नाम लैम्ब्डा है।

विधि 4 में आप वैरिएबल को अज्ञात (अनामित) लैम्ब्डा फ़ंक्शन के साथ प्रारंभ करते हैं जो स्ट्रिंग देता है।

3 और 4 के बीच अंतर यह है कि 4 वें में आप उस फ़ंक्शन को() से कॉल करते हैं ताकि आपको स्ट्रिंग मिल सके और पिछले में आप ऐसा नहीं करते हैं। dogName1, dogName2, dogName3, और dogName4 रूप

2

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

# 2 और # 3 नहीं बनाया गया, क्योंकि संकलक जानता था कि वे दोनों ही पढ़े जाते हैं। । पर आरंभ, एक अद्यतन करने के लिए कोशिश कर के बाद के बाद

- (# 2, के बावजूद एक var के रूप में घोषित किया जा रहा है, हमेशा वापस जाने के लिए "चार्ली" सेट कर दिया जाता

उन दो पंक्तियों बाहर टिप्पणी के बाद, मैं दो breakpoints निर्धारित किया है। अंत में मैं हर एक का एक print कर की कोशिश की

ब्रेकप्वाइंट # 1:। # 1 और # 4 के लिए "चार्ली" सेट कर रहे हैं, # 2 वहाँ (क्योंकि यह प्रारंभ नहीं किया गया है) नहीं है और # 3 प्रकट होता है प्रारंभ के रूप में है, लेकिन कोई मान के साथ (क्योंकि यह अभी तक नहीं बुलाया गया था। और हाँ, अंत में () स्मृति में कुछ initializes।

+०१२३५१६४१०

ब्रेकपॉइंट # 2: # 1 और # 4 को "स्नूपी" में अपडेट किया गया था। print की

परिणाम: # 1 और # 4 "Snoopy" थे, # 2 था "चार्ली" और # 3 था "(फंक्शन)"।

निष्कर्ष: # 1 और # 4 के बीच कोई अंतर नहीं है। प्रत्येक को var घोषित किया गया है और "चार्ली" का डिफ़ॉल्ट है। # 2, केवल पढ़ने के लिए है let की वजह से है और हमेशा वापस आ जाएगी "चार्ली"। # 3? यह एक उदाहरण बनाता है और निर्माण नहीं करता है अगर आप इसे बदलने की कोशिश - लेकिन मैं यह कैसे उपयोग करने के लिए पता नहीं है।

मैं अगर किसी को भी # 3 के बारे में जोड़ने के लिए अधिक है इस उत्तर अद्यतन करेगा।

1

को समझने के लिए मतभेद के एक और वर्णनात्मक उदाहरण

यह एक वर्ग है का उपयोग Foo

class Foo { 

    var className = "Foo" 

    var dogName1 : String { return "Charlie " + className } 

    let dogName2 = { 
     return "My name is Charlie" 
    } 

    var dogName3 : String = { 
     var string = "My" 
     string += " name" 
     string += " is" 
     string += " Charlie" 
     print(string) 
     return string 
    }() 

} 

अब चलो चलो चलो एक उदाहरण बनाएं

let foo = Foo() 
  • विधि 1

    let name = foo.className 
    foo.className = "Bar" 
    print(foo.className) // "Bar" 
    
  • विधि 2 गणना संपत्ति dogName1 केवल एक गेटर साथ है संग्रहीत संपत्ति className सेटर और गेटर के साथ है। इसका उपयोग गतिशील रूप से मूल्यों की गणना करने के लिए किया जा सकता है।

    print(foo.dogName1) // "Charlie Bar" 
    
  • विधि 3 प्रकार () -> String के बंद होने dogName2 है। यह एक चर को सौंपा जा सकता है और बाद में

    let dogName = foo.dogName2 // assigns the closure but does not return the string. 
    print(dogName()) // "My name is Charlie" 
    
  • विधि क्रियान्वित किया जा 4 चर dogName3 जो अपने बंद निष्पादित करता है तुरंत एक बार जब एक उदाहरण Foo() आरंभ नहीं हो जाता (print लाइन द्वारा साबित किया जाना)

    print(foo.dogName3) // "My name is Charlie" but does not execute the closure and print `string` again 
    
  • नहीं है यहां तक ​​कि एक विधि 5: यदि आप यह घोषणा करते dogName3के रूप में

    lazy var dogName3 : String = { 
    

    बंद निष्पादित नहीं है जब तक चर पहली बार पहुँचा जा सकता है। लाभ यह है कि आप self को बंद करने में भी उपयोग कर सकते हैं जो विधि 4 में संभव नहीं है।

संबंधित मुद्दे