स्विफ्ट फ़ंक्शंस बनाम गणना किए गए गुण


26

कहो कि मेरे पास एक वर्ग Eventहै:

class Event {
    private var attendees: [Person] = []

    // Case 1
    //*******
    // Should I use a func…
    func countOfAttendees() -> Int {
        return attendees.count
    }

    // …or a var
    var countOfAttendees: Int {
        return attendees.count
    }

    // Case 2
    //*******
    // Should I use a func…
    func countOfPaidAttendees() -> Int {
        return attendees.filter({$0.hasPaid}).count
    }

    // …or a var
    var countOfPaidAttendees: Int {
        return attendees.filter({$0.hasPaid}).count
    }
}

क्या ऊपर बताए गए 2 मामलों में कार्यों या कम्प्यूटेड गुणों का उपयोग करना सबसे अच्छा अभ्यास है ?


2
stackoverflow.com/questions/24035276/… ... संक्षेप में: 'अपने कार्यों को कार्य करने दें, और आपके गुण।'
रॉबर्ट हार्वे

जवाबों:


14

यूनिफ़ॉर्म एक्सेस सिद्धांत का पालन करें ,

एक मॉड्यूल द्वारा दी जाने वाली सभी सेवाएं एक समान संकेतन के माध्यम से उपलब्ध होनी चाहिए, जो यह विश्वास नहीं करता है कि क्या वे भंडारण के माध्यम से या संगणना के माध्यम से कार्यान्वित किए जाते हैं

मेरे लिए, इसका मतलब है कि मैं ऐसे फ़न नहीं लिखता हूँ जो कोई तर्क नहीं देते हैं और एक मूल्य वापस करते हैं। मैं हमेशा कम्प्यूटेड गुणों का उपयोग करता हूं। इस तरह, अगर मैं बाद में गणना की गई संपत्ति को संग्रहीत संपत्ति में बदलने का फैसला करता हूं, तो मैं अपने ऐप में हर जगह परियों को हटाने का आग्रह किए बिना और एक अलग "गेट्टर" विधि के बिना ऐसा कर सकता हूं जो सिर्फ संग्रहीत का मान लौटाता है संपत्ति, जो बहुत बेकार IMHO लगती है।

और अगर मैं एक संग्रहीत संपत्ति को एक संगणित में बदलता हूं, तो मुझे इसके अंत में, और हर जगह यह नहीं जोड़ा जाना चाहिए कि यह ऐप में उपयोग किया जाता है।


मैं मूल रूप से @ एंटोन के जटिलता उत्तर के साथ गया था, लेकिन व्यवहार में मुझे एहसास हुआ कि यह ऐसा है जो मैं इसे करता हूं ... डिफ़ॉल्ट रूप से गुण।
एशले मिल्स

17

मैं कहूंगा कि यह गणना बनाम उपयोग की आवृत्ति की जटिलता पर निर्भर करता है।

  • यदि यह O(1)/ है *, तो गणना की गई संपत्ति का उपयोग करें।
  • यदि यह O(N)+/ है rare-use, तो फ़ंक्शन का उपयोग करें।
  • यदि यह O(N)+/ है frequent-use, तो सोचें कि क्या भविष्य में आप जटिलता की भरपाई के लिए कैशिंग या अन्य "स्मार्ट" तकनीकों का उपयोग करने का निर्णय ले सकते हैं, यदि "हाँ" तो संपत्ति का उपयोग करें, यदि "नहीं-नहीं-नहीं, यह सिर्फ भारी है" तो फ़ंक्शन का उपयोग करें ।

2
अजीब बात है कि मैंने उसी तर्क का उपयोग करके इसे कैसे शुरू किया। यदि आप इसे "संपत्ति" होने का आभास दे सकते हैं, भले ही आपको एक हल्का प्रसंस्करण करना पड़े, जब तक कि यह वस्तु को परिवर्तित नहीं करता है, तब तक इसे संपत्ति बनायें।
डायल्सन सेल्स

9

मैंने हाल ही में कोटलिन सीखना शुरू किया है और उनके पास गणना गुणों का उपयोग करने के बारे में बहुत अच्छा अनुमान है:

गुण बनाम गुण

कुछ मामलों में बिना किसी तर्क के कार्य केवल पढ़ने योग्य गुणों के साथ विनिमेय हो सकते हैं। यद्यपि शब्दार्थ समान हैं, फिर भी एक से दूसरे को पसंद करने पर कुछ शैलीगत परंपराएँ हैं।

अंतर्निहित एल्गोरिथ्म पर एक फ़ंक्शन पर एक संपत्ति को प्राथमिकता दें:

  • फेंकता नहीं है
  • एक O (1) जटिलता है
  • गणना करने के लिए सस्ता है (या पहले रन पर पुकारा)
  • इनवॉइस पर एक ही परिणाम देता है

- https://kotlinlang.org/docs/reference/coding-conventions.html


स्विफ्ट के लिए 'थ्रो नहीं' भी महत्वपूर्ण है क्योंकि गुण फेंक नहीं सकते (अभी तक?)
alejandromp

"ओ (1) जटिलता है" प्रलेखन से हटा दिया गया है
महमूद शाहौद

7

स्विफ्ट में, मापदंडों और गणना किए गए गुणों के बिना कार्यों में लगभग समान क्षमताएं हैं (एक अंतर हो सकता है कि पैरामीटर के बिना एक फ़ंक्शन भी एक बंद है, जबकि एक गणना की गई संपत्ति नहीं है)।

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

एक बड़ा अंतर: यदि आप फ़ंक्शन या गणना की गई संपत्ति को दो बार कहते हैं तो क्या होगा? गणना की गई संपत्ति के लिए मुझे उम्मीद है कि x = संपत्ति; y = संपत्ति का x = गुण के समान व्यवहार है; y = x को छोड़कर यह थोड़ा धीमा हो सकता है। कार्यों के लिए, मुझे आश्चर्य नहीं होगा अगर व्यवहार अलग था।


4

का उपयोग करें countOfAttendeesऔर countOfPaidAttendees()


एक गणना किया गया चर वह है जो हर बार गणना किए जाने पर गणना किए गए मान को लौटाता है। यही है, यह एक मूल्य नहीं रखता है। आंतरिक रूप से इसे एक फ़ंक्शन के रूप में लागू किया जाता है।

एक फ़ंक्शन के साथ क्या अंतर है?

  • शब्दार्थ, एक राज्य है, एक कार्य एक क्रिया है।
  • एक फ़ंक्शन निजी संग्रहण तक पहुंच को नियंत्रित करता है। एक गणना चर एक अधिक कॉम्पैक्ट तरीके से ही कर सकता है। उदाहरण है
  • एक गणना किए गए चर का उपयोग केवीओ के साथ किया जा सकता है, जो #keypath के रूप में उत्तीर्ण होता है, और इसमें अवलोकन के लिए सुविधाएं हैं: willSet, didSet।

आपको एक चर का उपयोग करना चाहिए

  • यह फेंकता नहीं है
  • यह एक साधारण संपत्ति देता है
  • इसका कोई साइड इफेक्ट या क्रिया नहीं है
  • यह O (1) है, अर्थात यह एक महत्वपूर्ण लागत नहीं लगाता है। आपके उदाहरण में यह O (n) होगा।
  • यह आदर्श है। एकाधिक समान इनवॉइस समान मान लौटाते हैं या ऑब्जेक्ट को उसी स्थिति में सेट करते हैं।

एक समारोह में एक चर पसंद करने के लिए अप्रासंगिक कारण

  • एक कंप्यूटेड वैरिएबल आपको टाइपिंग () से बचाता है। हालांकि, स्पष्टता संक्षिप्तता से अधिक महत्वपूर्ण है, इसलिए यह एक कमजोर तर्क है।
  • एक चर केवल पढ़ने / लिखने के रूप में चर जा सकता है। एक फ़ंक्शन इंगित करता है कि यह हमेशा केवल पढ़ा जाता है। हालाँकि, Apple array.count जैसे केवल-पढ़ने योग्य चर के लिए गुणों का उपयोग करता है। जब संदेह में मंच के साथ स्थिरता चाहते हैं।

साधन

से  WWDC 2014 - 204 क्या कोको में नया क्या है  > 24:40 जब एक @property उपयोग करने के लिए

किसी ऐसी वस्तु के लिए संपत्ति का उपयोग करें जो किसी वस्तु के मूल्य या स्थिति या अन्य वस्तुओं से उसके संबंध के बारे में हो। खराब उम्मीदवार:

  • चीजें जो करती हैं: लोड, पार्स, टॉगल,…। उनके नाम में क्रियाएं हैं।
  • जनरेटर: init, copy, enumerated,…। ये विधियां बेकार नहीं हैं।
  • तरीके जो राज्य बदलते हैं: nextObject।

से  स्विफ्ट शैली एरिका Sadun द्वारा  > परिकलित गुण बनाम तरीके

एक संपत्ति एक अंतर्निहित गुणवत्ता को व्यक्त करती है, जबकि एक विधि एक क्रिया करती है।

  • विधियों में पैरामीटर हैं; गुण नहीं। साइड इफेक्ट्स के साथ किसी भी कॉल के लिए तरीकों को प्राथमिकता दें। यदि कोई विधि कुछ करती है (उदाहरण के लिए, यह लोड, पर्स, टॉगल या प्रिंट) या क्रिया नाम है, तो यह एक संपत्ति नहीं होनी चाहिए।
  • सरल मूल्यों के लिए गुणों को प्राथमिकता दें जो आप प्राप्त कर सकते हैं और / या सेट कर सकते हैं।
  • गुणों को एक प्रकार के उदाहरण के एक शब्दार्थ आंतरिक गुणवत्ता को व्यक्त करना चाहिए।
  • गुण आपको willSet और didSet के माध्यम से पर्यवेक्षकों को जोड़ने की अनुमति देते हैं। संग्रहीत उदाहरण गुणों के विपरीत, संग्रहीत प्रकार के गुणों को हमेशा डिफ़ॉल्ट मान दिया जाना चाहिए।

से  Kotlin कोडिंग सम्मेलनों> कार्यों गुण बनाम । ऊपर डैनियल का जवाब देखें ।

कोई प्रासंगिक जानकारी के साथ अन्य संसाधन:


3

मैं एक का उपयोग करेंगे func। ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग काम करता है बिना गणना गुण के ठीक। क्योंकि आपको एक मान वापस मिल रहा है जिसे गणना / फ़िल्टर किया गया था, कुछ तर्क दे सकते हैं कि एक गणना की गई संपत्ति सही लगती है। लेकिन यहाँ मेरी शिकायत है, अगर आप ऐसा करते हैं तो पठनीयता हिट हो जाती है, क्योंकि यह एक मूल्य की तरह लगता है।

इस संदर्भ में यह गणना मूल्य (और सौभाग्य से आईडीई हमें इससे बचने में मदद करता है) को असाइन करने का प्रयास करने के लिए समझ में नहीं आएगा लेकिन क्या होगा अगर मैं गणना की गई चीज़ को असाइन करने का प्रयास करता हूं लेकिन एक मूल्य जैसा दिखता है?

event.countOfAttendees = 0; // not possible

फोन करने वाले का उपयोग करते हुए पता है कि आप सीधे किसी मूल्य के साथ काम नहीं कर रहे हैं:

event.countOfAttendees()

मुझे लगता है कि अगर इसकी एक व्यवहारिक वस्तु यह दिखती है कि इसे डेटा संरचना की तरह देखने के बजाय व्यवहार करना चाहिए। यदि आपकी वस्तु गूंगी है और उसका कोई व्यवहार नहीं है तो उसे एनकैप्सुलेट करने की कोशिश क्यों करें? उस स्थिति में आपके पास केवल उपस्थित लोग ही सार्वजनिक हो सकते हैं

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