2017-01-11 11 views
7

मैं अपने स्वयं के कस्टम tableViewCell बनाने गया था और तब मैं एक त्रुटि कह मिल गया:आवश्यक प्रारंभकर्ता और नामित प्रारंभकर्ता के बीच क्या अंतर है?

'आवश्यक' प्रारंभकर्ता 'init (सांकेतिक शब्दों में बदलनेवाला :)' 'UITableViewCell'

के उपवर्ग द्वारा प्रदान किया जाना चाहिए मैंने इसे देखा और जाहिर है कि इसे भी लागू करना जरूरी है। लेकिन इस बनाम नामित initializers

Apple Docs आवश्यक के बारे में मेरे भ्रम की स्थिति पैदा कहते हैं:

आवश्यक initializers:

एक वर्ग प्रारंभकर्ता की परिभाषा से पहले आवश्यक संशोधक लिखें कि हर इंगित करने के लिए कक्षा के उप-वर्ग को लागू करना चाहिए कि प्रारंभकर्ता:

मनोनीत initializers

मनोनीत initializers एक वर्ग के लिए प्राथमिक initializers हैं। नामित प्रारंभकर्ता पूरी तरह से द्वारा पेश की जाने वाली सभी गुणों को प्रारंभ करता है और सुपरक्लास श्रृंखला को प्रारंभिक प्रक्रिया जारी रखने के लिए उपयुक्त सुपरक्लास प्रारंभकर्ता को कॉल करता है।

निम्नलिखित बयानों को सही कर रहे हैं:

  • एक आवश्यक प्रारंभकर्ता हमेशा एक नामित प्रारंभकर्ता
  • हर नामित प्रारंभकर्ता जरूरी नहीं है एक आवश्यक प्रारंभकर्ता है
  • एक वर्ग केवल एक आवश्यक प्रारंभकर्ता हो सकता है हालांकि, इसमें एकाधिक नामित प्रारंभकर्ता हो सकते हैं?

ऐसा कहकर मैंने अभी भी अपने कार्यात्मक मतभेदों को पूरी तरह से समझ नहीं लिया है।

+0

मेरा मानना ​​है कि आपके पास एक आवश्यक सुविधा प्रारंभकर्ता हो सकता है, इसलिए पहला कथन सही नहीं है। – dan

उत्तर

13

आवश्यक प्रारंभिक और नामित प्रारंभिक वास्तव में संबंधित नहीं हैं, हालांकि संबंधित कीवर्ड required और convenience दोनों उप-वर्गों पर प्रतिबंध निर्दिष्ट करने के लिए उपयोग किए जाते हैं।

आवश्यक Initialisers

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

protocol TestProtocol { 
    init() 
} 

class TestClass: TestProtocol { 
    required init() { 

    } 
} 

यहाँ, required कीवर्ड क्योंकि TestClass के किसी भी उपवर्गों भी init() प्रदान करनी चाहिए मौजूद होना चाहिए (क्योंकि वे भी TestProtocol के अनुरूप)।

एक आवश्यक initialiser रखने से आपको यह जानकर क्या यह संकलन समय है, जो कई कारणों से के लिए उपयोगी है पर है बिना एक वर्ग आरंभ करने के लिए अनुमति देता है:

let classType: TestProtocol.Type = TestClass.self 
let object = classType.init() 

यदि आपका वर्ग एक के साथ एक, कई प्रोटोकॉल के अनुसार चलाया उदाहरण के लिए अलग initialiser, उन initialisers से प्रत्येक भी आवश्यक किया जाना चाहिए:

protocol OtherProtocol { 
    init(thing: Int) 
} 

class OtherClass: TestClass, OtherProtocol { 
    let thing: Int 

    required init() { // Required from superclass/its protocol 
     self.thing = 0 
    } 

    required init(thing: Int) { // Required from new protocol 
     self.thing = thing 
    } 
} 

ध्यान दें कि super.init() जोड़ने इस विशेष मामले में आवश्यक नहीं है, क्योंकि स्विफ्ट कॉल स्वतः शामिल हो जाएगी, तो यह कोई पैरामीटर लेता है ।

उपरोक्त सभी उदाहरणों में, प्रारंभिक नामकों को नामित किया गया है क्योंकि उनमें convenience कीवर्ड शामिल नहीं है।

class BaseClass { 
    let value: Int 

    required init(value: Int) { 
     self.value = value 
    } 
} 

class SubClass: BaseClass { 
    required init(value: Int) { // Required from superclass 
     super.init(value: value) // Must call desginated initialiser of superclass 
    } 
} 

let someBaseClassType: BaseClass.Type = SubClass.self 
let someBaseClassInstance = someBaseClassType.init(value: 1) 

मनोनीत Initialisers

:

यहां तक ​​कि अगर आप किसी भी प्रोटोकॉल नहीं था, तब भी आप required के उपयोग के एक वर्ग का एक प्रकार है जो संकलन समय पर नहीं जाना जाता है initialising द्वारा बना सकते हैं नामित प्रारंभिक एक ऐसा है जो सुविधा प्रारंभकर्ता नहीं है (यानी, convenience के साथ चिह्नित)। एक नामित प्रारंभिक व्यक्ति को यह सुनिश्चित करना होगा कि कक्षा के सभी गुणों के प्रारंभकर्ता से पहले एक मूल्य हो (या एक सुपर प्रारंभकर्ता कहा जाता है)। सुविधा प्रारंभकर्ताओं के पास केवल यह आवश्यकता नहीं है क्योंकि उन्हें स्वयं नामित प्रारंभिक कॉलर को कॉल करना होगा।

class OtherSubClass: BaseClass { 
    convenience required init(value: Int) { 
     self.init() // Must call designated initialiser of this class 
    } 

    init() { 
     super.init(value: 0) // Must call designated initialiser of superclass 
    } 
} 

(यह काफी काल्पनिक उदाहरण है।)

मेरे अनुभव में, सुविधा initialisers शायद ही कभी उपयोगी होते हैं और मैं समस्याओं को हल करने के बजाय नामित initialisers पर वैकल्पिक तर्क का उपयोग कर हल किया जा सकता को खोजने के लिए करते हैं। किसी को इस तथ्य पर विचार करने की भी आवश्यकता है कि initialisers can't call convenience initialisers on their superclass, इसलिए सुनिश्चित करें कि आपके पास कोई सुविधा प्रारंभकर्ता नहीं है जो कार्यक्षमता प्रदान करता है कि आपके नामित प्रारंभिक लोग ऐसा नहीं करते हैं कि आप अपनी कक्षा को उप-वर्गीकृत करना चाहते हैं!


Structs और enums required या convenience कीवर्ड क्योंकि उन कीवर्ड दोनों उपवर्गों के लिए initialisation नियम है, जो केवल class तों समर्थन इंगित करने के लिए उपयोग किया जाता है का उपयोग नहीं करते: required कीवर्ड इंगित करता है कि उपवर्गों कि initialiser प्रदान करनी चाहिए, और convenience कीवर्ड इंगित करता है कि उप-वर्ग उस प्रारंभकर्ता को कॉल नहीं कर सकते हैं। कीवर्ड न होने के बावजूद, उन्हें अभी भी प्रारंभिक किसी भी प्रोटोकॉल में परिभाषित प्रारंभिक प्रदान करना होगा, और आप convenience कीवर्ड के बिना 'सुविधाजनक' प्रारंभिक प्रारंभकर्ता लिख ​​सकते हैं जो self.init पर कॉल करते हैं।


अपने बयान पर प्रतिक्रिया करने के लिए:

  • आवश्यक initialisers नामित किए जाने की जरूरत नहीं है।
  • नामित प्रारंभिक व्यक्तियों की आवश्यकता नहीं है।
  • कक्षाओं में कई आवश्यक और नामित प्रारंभिक खिलाड़ी हो सकते हैं।
+0

कोड-स्निपेट के लिए धन्यवाद, यह समझने के लिए बहुत आसान बनाता है। क्या आप एकाधिक आवश्यक प्रारंभकर्ताओं के लिए एक साधारण उदाहरण भी जोड़ सकते हैं? मुझे – Honey

+0

वाह का अर्थ बनाने में कठिनाई हो रही है। मैं "टॉप-डाउन" भूमि से आया हूं और अपने 20 साल पहले ओओपी सीखा था। अभी भी प्रोटोकॉल प्रोग्रामिंग सीखना। यह मेरे दिमाग को उड़ाता है। ऊपर मतदान किया। – dfd

+0

@ हनी: हो गया, कोड स्निपेट सभी एक-दूसरे से चलते हैं। – Robert

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