स्विफ्ट इनिशियलाइज़ सबक्लास को पहले उचित फ़ील्ड क्यों देता है?


9

भाषा स्विफ्ट में, एक उदाहरण को शुरू करने के लिए, उस वर्ग के सभी क्षेत्रों को भरना होता है, और उसके बाद ही सुपरस्टारडम को कॉल करना होता है:

class Base {
    var name: String

    init(name: String) {
        self.name = name
    }
}

class Derived: Base {
    var number: Int

    init(name: String, number: Int) {
        // won't compile if interchange lines
        self.number = number
        super.init(name)
    }
}

मेरे लिए यह पीछे की ओर लगता है, क्योंकि उदाहरण selfको इसके क्षेत्रों में मान निर्दिष्ट करने से पहले बनाने की आवश्यकता होती है, और यह कोड ऐसा आभास देता है जैसे कि असाइनमेंट के बाद ही चेनिंग होती है। इसके अलावा, सुपरक्लास के पास अपने उपवर्ग की पेश की गई विशेषताओं को पढ़ने का कोई कानूनी साधन नहीं है, इसलिए इस मामले में सुरक्षा की गणना नहीं की जाती है।

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

सुपरकंडक्टर को कॉल करने से पहले खेतों को परिभाषित करने की आवश्यकता के लिए इस विकल्प के पीछे क्या तर्क है?


दिलचस्प। क्या कोई प्रतिबंध है जहां विधि आह्वान (आभासी, विशेष रूप से) रखा जा सकता है, जैसे कि, केवल कहने के बाद? C # में, एक उपवर्ग के फ़ील्ड को डिफ़ॉल्ट मान दिया जाता है, फिर चाइनिंग / सुपरक्लास निर्माण होता है, फिर आप उन्हें असली, IIRC के लिए आरंभ कर सकते हैं ..
Erik Eidt

3
मुद्दा यह है कि अप्रतिबंधित पहुंच की अनुमति देने से पहले आपको सभी फ़ील्ड को इनिशियलाइज़ करना होगा self
कोडइन्कॉच

@ErikEidt: स्विफ्ट में, केवल वैकल्पिक फ़ील्ड स्वचालित रूप से शून्य पर आरंभीकृत होते हैं।
gnasher729

जवाबों:


9

C ++ में, जब आप व्युत्पन्न ऑब्जेक्ट बनाते हैं, तो बेस कंस्ट्रक्टर के चलते समय यह बेस ऑब्जेक्ट के रूप में शुरू होता है, इसलिए जब बेस कंस्ट्रक्टर चलता है, तो व्युत्पन्न सदस्य मौजूद नहीं होते हैं। इसलिए उन्हें आरंभीकृत होने की आवश्यकता नहीं है, और वे संभवतः आरंभिक नहीं हो सकते। केवल जब बेस कंस्ट्रक्टर समाप्त हो गया है, तो वस्तु को एक व्युत्पन्न वस्तु के साथ बदल दिया जाता है जिसमें बहुत सारे असिंचित क्षेत्र होते हैं जो आप तब आरंभ करते हैं।

स्विफ्ट में, जब आप एक व्युत्पन्न वस्तु बनाते हैं, तो यह शुरू से ही एक व्युत्पन्न वस्तु है। यदि विधियों को ओवरराइड किया जाता है, तो बेस इनिट विधि पहले से ही ओवरराइड विधियों का उपयोग करेगी, जो कि व्युत्पन्न सदस्य चर का उपयोग कर सकती है। इसलिए बेस इनिट विधि के आने से पहले सभी व्युत्पन्न सदस्य चर आरंभ किए जाने चाहिए

पुनश्च। आपने Objective-C का उल्लेख किया है। ऑब्जेक्टिव-सी में, सब कुछ स्वचालित रूप से 0 / nil / NO के लिए शुरू हो जाता है। लेकिन अगर वैरिएबल को इनिशियलाइज़ करने के लिए वह वैल्यू सही वैल्यू नहीं है, तो बेस इनिट विधि आसानी से ओवरराइड होने वाली विधि को कॉल कर सकती है और सही मूल्य के बजाय 0 के मान के साथ अभी तक इनिशियलाइज़ेड वैरिएबल का उपयोग नहीं करती है। ऑब्जेक्टिव-सी में, यह भाषा के नियमों का उल्लंघन नहीं है (यही कारण है कि यह काम करने के लिए परिभाषित है) लेकिन स्पष्ट रूप से आपके कोड में एक बग है। स्विफ्ट में, भाषा द्वारा उस बग की अनुमति नहीं है।

पुनश्च। एक टिप्पणी है "क्या यह शुरू से एक व्युत्पन्न वस्तु है, या क्या यह भाषा के नियमों के कारण अवलोकन योग्य नहीं है"? बेस इनिट विधि कहे जाने से पहले व्युत्पन्न वर्ग ने अपने स्वयं के सदस्यों को आरंभीकृत किया है, और ये व्युत्पन्न सदस्य अपने मूल्यों को बनाए रखते हैं। तो या तो वह है समय में एक व्युत्पन्न वस्तु बेस init कहा जाता है, या संकलक कुछ नहीं बल्कि विचित्र क्या करना होगा। और बेस इनिट विधि के बाद सभी बेस इंस्टेंस सदस्यों को इनिशियलाइज़ किया गया है, इसे ओवरराइड फ़ंक्शंस कह सकते हैं और यह साबित होगा कि यह व्युत्पन्न वर्ग का एक उदाहरण है।


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

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

9

यह स्विफ्ट के सुरक्षा नियमों से आता है, जैसा कि भाषा डॉक के इनिशियलाइज़ेशन पेज पर सेक्शन टू-फेज़ इनिशियलाइज़ेशन में बताया गया है ।

यह सुनिश्चित करता है कि हर क्षेत्र उपयोग से पहले सेट किया गया है (esp। संकेत, दुर्घटनाओं से बचने के लिए)।

स्विफ्ट इसे दो-चरण के आरंभीकरण अनुक्रम के साथ प्राप्त करता है: प्रत्येक इनिशलाइज़र को अपने सभी इंस्टेंस फ़ील्ड्स को इनिशियलाइज़ करना होगा, फिर उसी तरह से करने के लिए एक सुपरक्लास इनिशियलाइज़र को कॉल करें, और उसके बाद ही ट्री अप होने पर इन इनिशियलाइज़र को selfपॉइंटर को भागने देने की अनुमति दी जाती है , कॉल इंस्टेंस तरीकों, या उदाहरण के गुणों के मूल्यों को पढ़ें।

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

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


बेशक, यह एमआई के साथ बहुत कठिन होगा।
डेडुप्लिकेटर

3

विचार करें

  • बेस क्लास में परिभाषित एक आभासी पद्धति को व्युत्पन्न वर्ग में फिर से परिभाषित किया जा सकता है।
  • आधार वर्ग के ठेकेदार इस आभासी विधि को प्रत्यक्ष या अप्रत्यक्ष रूप से कह सकते हैं।
  • नए सिरे से परिभाषित आभासी विधि (व्युत्पन्न वर्ग में) व्युत्पन्न वर्ग ठेकेदार में सही ढंग से व्युत्पन्न वर्ग जा रहा है सेट में एक क्षेत्र के मूल्य पर निर्भर हो सकता है।
  • व्युत्पन्न वर्ग के ठेकेदार बेस क्लास में एक विधि कह सकते हैं जो बेस क्लास ठेकेदार में सेट किए गए फ़ील्ड पर निर्भर करता है।

इसलिए कोई सरल डिजाइन नहीं है जो वर्चुअल तरीकों की अनुमति देने पर ठेकेदार को सुरक्षित बनाता है , स्विफ्ट को दो-चरण की शुरुआत की आवश्यकता से इन मुद्दों से बचा जाता है, इसलिए प्रोग्रामर को बेहतर सुरक्षा प्रदान करता है, जबकि एक अधिक जटिल भाषा भी होती है।

यदि आप इन मुद्दों को अच्छे तरीके से हल कर सकते हैं, तो "गो" पास न करें, सीधे अपने PHD के संग्रह पर आगे बढ़ें ...

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