मौजूदा उत्तर केवल convenience
कहानी का आधा हिस्सा बताते हैं । कहानी का दूसरा आधा हिस्सा, जो मौजूदा उत्तरों में से कोई भी कवर नहीं करता है, डेसमंड ने टिप्पणियों में पोस्ट किए गए प्रश्न का उत्तर दिया है:
स्विफ्ट मुझे convenience
अपने इनिशियलाइज़र के सामने रखने के लिए मजबूर क्यों करेगा क्योंकि मुझे self.init
इससे कॉल करने की आवश्यकता है ? `
मैंने इस उत्तर में इसे थोड़ा सा स्पर्श किया , जिसमें मैंने स्विफ्ट के कई प्रारंभिक नियमों को विवरण में शामिल किया, लेकिन मुख्य फोकस required
शब्द पर था । लेकिन यह जवाब अभी भी कुछ ऐसा था जो इस प्रश्न और इस उत्तर के लिए प्रासंगिक है। हमें यह समझना होगा कि स्विफ्ट इनिशियलाइज़र इनहेरिटेंस कैसे काम करता है।
क्योंकि स्विफ्ट एकतरफा चर के लिए अनुमति नहीं देता है, तो आपको उस वर्ग से सभी (या किसी भी) इनिशियलाइज़र को विरासत में प्राप्त करने की गारंटी नहीं है। यदि हम अपने उपवर्ग में किसी भी प्रकार के असंगठित उदाहरण चर जोड़ते हैं, तो हमने आरंभीकरण को रोक दिया है। और जब तक हम अपने खुद के इनिशियलाइज़र नहीं जोड़ते, तब तक कंपाइलर हमारे ऊपर चिल्लाएगा।
स्पष्ट होने के लिए, एक uninitialized इंस्टेंस वैरिएबल कोई भी इंस्टेंस वैरिएबल है जिसे डिफॉल्ट वैल्यू नहीं दिया गया है (ध्यान में रखते हुए कि ऑप्शनल और इम्प्लांटली अनप्रैप्टेड ऑप्शंस अपने आप डिफॉल्ट वैल्यू मान लेते हैं nil
)।
तो इस मामले में:
class Foo {
var a: Int
}
a
एक असंक्रमित उदाहरण चर है। यह तब तक संकलित नहीं होगा जब तक हम a
एक डिफ़ॉल्ट मूल्य नहीं देते :
class Foo {
var a: Int = 0
}
या a
एक आरंभिक विधि में आरंभ करें:
class Foo {
var a: Int
init(a: Int) {
self.a = a
}
}
अब, देखते हैं कि अगर हम उपवर्ग करते हैं तो क्या होगा Foo
?
class Bar: Foo {
var b: Int
init(a: Int, b: Int) {
self.b = b
super.init(a: a)
}
}
सही? हमने एक वैरिएबल जोड़ा है, और हमने एक इनिशियलाइज़र जोड़ा है b
ताकि एक मान सेट किया जा सके ताकि यह संकलित हो जाए। आप किस भाषा से आ रहे हैं, इस पर निर्भर करते हुए, आप उम्मीद कर सकते हैं कि आपको इनिशियलाइज़र Bar
विरासत में मिला है । लेकिन यह नहीं है। और यह कैसे हो सकता है? कैसे करता है पता है कि कैसे करने के लिए एक मूल्य निर्दिष्ट है कि चर जोड़ा? यह नहीं है इसलिए हम एक ऐसे इनिशियलाइज़र के साथ एक उदाहरण को इनिशियलाइज़ नहीं कर सकते हैं जो हमारे सभी मूल्यों को इनिशियलाइज़ नहीं कर सकता है।Foo
init(a: Int)
Foo
init(a: Int)
b
Bar
Bar
इसका किसी से क्या लेना-देना है convenience
?
ठीक है, आइए आरंभिक विरासत पर नियमों को देखें :
नियम 1
यदि आपका उप-वर्ग किसी भी निर्दिष्ट इनिशियलाइज़र को परिभाषित नहीं करता है, तो यह स्वचालित रूप से अपने सभी सुपरक्लास नामित इनिशियलाइज़र को विरासत में देता है।
नियम २
यदि आपका उप-वर्ग अपने सभी सुपरक्लास नामित इनिशियलाइज़र के कार्यान्वयन को प्रदान करता है - या तो उन्हें नियम 1 के अनुसार विरासत में मिला है, या इसकी परिभाषा के भाग के रूप में एक कस्टम कार्यान्वयन प्रदान करता है - तो यह स्वचालित रूप से सभी सुपरक्लास सुविधा इनिशियलाइज़र को विरासत में मिला है।
सूचना नियम 2, जिसमें सुविधा प्रारंभकों का उल्लेख है।
इसलिए convenience
कीवर्ड जो कुछ भी करता है वह हमें इंगित करता है कि कौन से इनिशियलाइज़र को उन उपवर्गों द्वारा विरासत में मिला जा सकता है जो डिफ़ॉल्ट मानों के बिना उदाहरण चर जोड़ते हैं।
आइए इस उदाहरण को लें Base
:
class Base {
let a: Int
let b: Int
init(a: Int, b: Int) {
self.a = a
self.b = b
}
convenience init() {
self.init(a: 0, b: 0)
}
convenience init(a: Int) {
self.init(a: a, b: 0)
}
convenience init(b: Int) {
self.init(a: 0, b: b)
}
}
ध्यान दें, हमारे पास तीन हैं convenience
इनिशियलाइज़र हैं। इसका मतलब है कि हमारे पास तीन शुरुआती हैं जो विरासत में मिले हैं। और हमारे पास एक निर्दिष्ट इनिशियलाइज़र है (एक निर्दिष्ट इनिशियलाइज़र केवल कोई इनिशियलाइज़र है जो एक सुविधा आरम्भक नहीं है)।
हम चार अलग-अलग तरीकों से बेस क्लास के इंस्टेंस को इंस्टेंट कर सकते हैं:
तो, चलो एक उपवर्ग बनाएँ।
class NonInheritor: Base {
let c: Int
init(a: Int, b: Int, c: Int) {
self.c = c
super.init(a: a, b: b)
}
}
हमें विरासत में मिली है Base
। हमने अपना खुद का इंस्टालेशन वेरिएबल जोड़ा है और हमने इसे डिफॉल्ट वैल्यू नहीं दिया है, इसलिए हमें अपने इनिशियलाइज़र को जोड़ना होगा। हमने एक जोड़ा init(a: Int, b: Int, c: Int)
, लेकिन यह Base
वर्ग के निर्दिष्ट इनिशियलाइज़र के हस्ताक्षर से मेल नहीं खाता init(a: Int, b: Int)
:। इसका मतलब है, हम किसी भी शुरुआती से विरासत में नहीं मिल रहे हैं Base
:
इसलिए, अगर हमें विरासत में मिला है Base
, तो क्या होगा , लेकिन हमने आगे बढ़कर एक इनिशियलाइज़र को लागू किया, जो निर्दिष्ट इनिशियलाइज़र से मेल खाता है Base
?
class Inheritor: Base {
let c: Int
init(a: Int, b: Int, c: Int) {
self.c = c
super.init(a: a, b: b)
}
convenience override init(a: Int, b: Int) {
self.init(a: a, b: b, c: 0)
}
}
अब, हमने इस कक्षा में सीधे लागू किए गए दो इनिशियलाइज़र्स के अलावा, क्योंकि हमने इनिशियलाइज़र मिलान Base
क्लास के निर्दिष्ट इनिशियलाइज़र को लागू किया है, हमें Base
क्लास के सभी convenience
इनिशियलाइज़र्स विरासत में मिलते हैं :
तथ्य यह है कि मिलान हस्ताक्षर के साथ इनिशलाइज़र को चिह्नित किया जाता है, convenience
यहाँ कोई अंतर नहीं है। इसका केवल यह अर्थ है कि Inheritor
केवल एक निर्दिष्ट इनिशियलाइज़र है। इसलिए अगर हमें विरासत में मिली है Inheritor
, तो हमें बस उस एक नामित इनिशियलाइज़र को लागू करना होगा, और उसके बाद हम Inheritor
इनिशियलाइज़र को इनहेरिट करेंगे , जिसका अर्थ है कि हमने सभी Base
इनिशियलाइज़ इनिशियलाइज़र्स को लागू किया है और इसके convenience
इनिशियलाइज़र को इनहेरिट किया जा सकता है।