स्विफ्ट प्रोग्रामिंग: संग्रहीत संपत्ति में गेट्टर / सेटर


102

मैं स्विफ्ट में संग्रहीत संपत्ति के सेटर को कैसे अधिलेखित कर सकता हूं?

ओबज-सी में, मैं इसके सेटर को ओवरराइट कर सकता हूं, लेकिन स्विफ्ट को संग्रहीत संपत्ति के लिए इस्तेमाल होने वाले गेटटर / सेटरों के बारे में खुश नहीं लगता है।

कहो कि मेरे पास एक Cardवर्ग है जिसमें एक संपत्ति है rank। मैं नहीं चाहता कि ग्राहक इसे कोई अमान्य मान दे, इसलिए, उद्देश्य-सी में, मैं इसे अधिलेखित कर सकता हूं setRankताकि यह अतिरिक्त जांच करे। लेकिन willSetस्विफ्ट में मदद नहीं लगती क्योंकि newValueस्थिर है और यह असाइन करने का कोई मतलब नहीं है rankक्योंकि सेटर को लूप में कहा जाएगा।


क्या आपको ऐसा करने का एक तरीका मिला है? मुझे खुद इस तरह की कार्यक्षमता की आवश्यकता है ...
मिहाई फ्रेटु

मुझे यह मिला। मेरा जवाब
देखिए

WhatGet या एनालॉग के बारे में?
fnc12

जवाबों:


107

ठीक। स्विफ्ट पर सेब प्रलेखन के माध्यम से पढ़ना मुझे यह मिला :

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

तो आपको बस इतना करना है:

var rank: Int = 0 {
    didSet {
        // Say 1000 is not good for you and 999 is the maximum you want to be stored there
        if rank >= 1000  {
            rank = 999
        }
    }
}

WhatGet या एनालॉग के बारे में?
fnc12

यकीन नहीं होता कि मैं आपका सवाल समझ गया हूं। क्या आप अधिक विशिष्ट हो सकते हैं, कृपया?
मिहाई फ्रेटु

मुझे कुछ कोड प्राप्त करने से पहले आह्वान करना होगा। मैं obj-c में यह प्रदर्शन करने में सक्षम था, लेकिन मैं यह नहीं देख सकता कि स्विफ्ट में यह कैसे प्रदर्शन करूं। केवल एक चीज जो मैं देख रहा हूं वह दो गुणों का उपयोग करना है: एक सार्वजनिक है और एक निजी है, सार्वजनिक मेरे कोड को आमंत्रित करता है और निजी संपत्ति के मूल्य को वापस करता है। यही कारण है कि मैंने didGet के बारे में पूछा
fnc12

आपके पास केवल एक गणना की गई संपत्ति के लिए एक गटर हो सकता है। उदाहरण के लिएvar rankTimesTwo: Int { get { return rank * 2 } }
मिहाई फ्रेटु

2
एक जादू की तरह काम करता है! संपत्ति को init () में सेट करते समय इसे खबरदार नहीं कहा जाएगा
Christoph

35

आप ओवरराइड नहीं कर सकते get/ setएक संग्रहीत संपत्ति के लिए लेकिन आप संपत्ति पर्यवेक्षकों का उपयोग कर सकते willSet/ didSet:

var totalSteps: Int = 0 {
    willSet(newTotalSteps) {
        println("About to set totalSteps to \(newTotalSteps)")
    }
    didSet {
        if totalSteps > oldValue  {
            println("Added \(totalSteps - oldValue) steps")
        }
    }
}

डिफ़ॉल्ट पैरामीटर नाम के newValueलिए willSetऔर के oldValueलिए कर रहे हैं didSet, या आप उन्हें खुद के रूप में नाम दे सकते हैं willSet(newTotalSteps)


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

कहो कि मेरे पास एक Cardवर्ग है जिसमें एक संपत्ति है rank। मैं नहीं चाहता कि ग्राहक इसे कोई मूल्य दे, इसलिए, उद्देश्य-सी में, मैं इसे अधिलेखित कर सकता हूं setRankताकि यह अतिरिक्त जांच करता है। लेकिन willSetस्विफ्ट में मदद नहीं लगती क्योंकि newValueस्थिर है और यह असाइन करने का कोई मतलब नहीं है rankक्योंकि सेटर को लूप में कहा जाएगा।
बोहल

2
मुझे पूरी तरह से यकीन नहीं है कि आपका क्या मतलब है लेकिन क्या आप इसे सेट होने के बाद didSetजांचने के लिए उपयोग नहीं कर सकते हैं rankऔर यदि यह सत्यापन विफल हो जाता है, तो इसे किसी और चीज़ पर रीसेट करें oldValue?
जोसेफ मार्क

9

प्राप्त करें और सेट गणना की गई संपत्तियों के लिए हैं (उनके पास कोई बैकिंग स्टोर नहीं है)। (मेरी राय में, कीवर्ड 'var' यहाँ भ्रामक है)

  • विलसेट और डिडसेट को एक परिवर्तनशील चर के लिए कहा जाता है (किसी भी परिवर्तन को ओवरराइड करने के लिए डिडसेट का उपयोग करें)
  • सेट और प्राप्त शुद्ध रूप से गणना गुणों के लिए हैं

9

यदि आप didSet का उपयोग नहीं करना चाहते हैं, जिसमें समस्या है कि संपत्ति का मूल्य अस्थायी रूप से गलत है, तो आपको इसके साथ एक गणना की गई संपत्ति को लपेटना चाहिए।

private var _foo:Int = 0
var foo:Int {
    get {
        return _foo
    }
    set {
        if(newValue > 999) {
            _foo = 999
        } else {
            _foo = newValue
        }
    }
}

या:

private var _foo:Int = 0
var foo:Int {
    get {
        return _foo
    }
    set {
        guard newValue <= 999 else {
            _foo = 999
            return
        }
        _foo = newValue
    }
}

इसका दो चर का उपयोग करने का कोई मतलब नहीं है।
पीयूष

1
यह केवल एक संपत्ति (चर) का उपयोग कर रहा है: fooकेवल एक गणना अभिव्यक्ति है _foo, "var" कीवर्ड को आपको मूर्ख मत बनने दो! इसका मतलब यह है कि निजी नाम स्थान से दो प्रविष्टियाँ सुलभ हैं, लेकिन संरक्षित / सार्वजनिक कोई असर नहीं है और fooहर समय मान्य का मूल्य रखता है । यह अनिवार्य रूप से "दृश्य" पैटर्न है। आपके द्वारा पुनर्लेखन के साथ जो समस्या आती है didSet, इसके अलावा अमान्य होने की अवधि के अलावा, यह एक अनंत लूप के लिए महत्वपूर्ण क्षमता है क्योंकि आप didSetभीतर से हैंडलर को फिर से प्रस्तुत कर रहे हैं didSet
जिम ड्रिस्कॉल

-8

सरलीकृत उदाहरण:

class Shape {
    var sideLength: Double {
    get {
        return self.sideLength
    }
    set {
        // Implement the setter here.
        self.sideLength = newValue
    }
    }
}

पूर्ण उदाहरण

की जाँच करें perimeterइस उदाहरण में।

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

class EquilateralTriangle: NamedShape {
    var sideLength: Double = 0.0

    init(sideLength: Double, name: String) {
        self.sideLength = sideLength
        super.init(name: name)
        numberOfSides = 3
    }

    var perimeter: Double {
    get {
        return 3.0 * sideLength
    }
    set {
        sideLength = newValue / 3.0
    }
    }

    override func simpleDescription() -> String {
        return "An equilateral triagle with sides of length \(sideLength)."
    }
}
var triangle = EquilateralTriangle(sideLength: 3.1, name: "a triangle")
triangle.perimeter
triangle.perimeter = 9.9
triangle.sideLength”

3
इस मामले में, perimeterअभी भी एक गणना की गई संपत्ति है। एक संगणित संपत्ति को पेश किए बिना मैं साइडलॉग्राइट को कैसे अधिलेखित करूं?
बोहल

@bohanl मैंने एक सरल उदाहरण का उपयोग करके जोड़ा हैgetset
माइक रैपादास

6
आपका "पूर्ण उदाहरण" एक संगृहीत संपत्ति दिखाता है, संग्रहीत संपत्ति नहीं है, और आपका "सरल उदाहरण" काम नहीं करता है।
कालेब

मुझे सही साबित होना है। यह ऐसा है मानो ऑब्जेक्टिव-सी में @property (ऑटो-सिंथेसाइज्ड गेटर्स + सेटर्स) का एब्स्ट्रैक्शन स्विफ्ट में अनएब्रेटेड हो गया है। विडंबना ...
माइक रैपादास

6
आप "सरलीकृत उदाहरण" हैं जो अपने आप को एक गटर के भीतर एक कॉलगर्ल कह रहा है। इन्फ लूप ... क्रैश।
1
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.