समस्या यह है कि आप एक वादा कर रहे हैं कि संकलक साबित नहीं कर सकता है कि आप रखेंगे।
तो आपने यह वादा किया है: कॉलिंग copy()
अपने प्रकार को लौटाएगा, पूरी तरह से प्रारंभिक।
लेकिन फिर आपने copy()
इस तरह से लागू किया:
func copy() -> Self {
return C()
}
अब मैं एक उपवर्ग हूं जो ओवरराइड नहीं करता है copy()
। और मैं एक लौटाता हूं C
, पूरी तरह से इनिशियलाइज्ड नहीं Self
(जो मैंने वादा किया था)। तो यह अच्छा नहीं है। कैसा रहेगा:
func copy() -> Self {
return Self()
}
ठीक है, यह संकलित नहीं होगा, लेकिन अगर यह किया, तो भी यह अच्छा नहीं होगा। उपवर्ग में कोई तुच्छ कंस्ट्रक्टर D()
नहीं हो सकता है , इसलिए कानूनी भी नहीं हो सकता है। (हालांकि नीचे देखें।)
ठीक है, अच्छी तरह से कैसे के बारे में:
func copy() -> C {
return C()
}
हां, लेकिन वह वापस नहीं आया Self
। यह लौट आता है C
। आप अभी भी अपना वादा नहीं निभा रहे हैं।
"लेकिन ObjC यह कर सकता है!" अच्छी तरह की। ज्यादातर क्योंकि यह परवाह नहीं करता है यदि आप अपना वादा रखते हैं जिस तरह से स्विफ्ट करता है। यदि आप copyWithZone:
उपवर्ग में लागू करने में विफल रहते हैं , तो आप अपनी वस्तु को पूरी तरह से शुरू करने में विफल हो सकते हैं। संकलक आपको चेतावनी भी नहीं देगा कि आपने ऐसा किया है।
"लेकिन ObjC में सबसे अधिक सब कुछ स्विफ्ट में अनुवाद किया जा सकता है, और ObjC के पास है NSCopying
।" हां यह करता है, और यहां बताया गया है कि यह कैसे परिभाषित किया गया है:
func copy() -> AnyObject!
तो आप भी ऐसा ही कर सकते हैं (इसका कोई कारण नहीं है! यहाँ):
protocol Copyable {
func copy() -> AnyObject
}
वह कहता है, "मैं कुछ भी वादा नहीं कर रहा हूं कि आपको क्या मिलेगा।" आप यह भी कह सकते हैं:
protocol Copyable {
func copy() -> Copyable
}
यह एक वादा है जिसे आप कर सकते हैं।
लेकिन हम थोड़ी देर के लिए सी ++ के बारे में सोच सकते हैं और याद रखें कि एक वादा है जिसे हम कर सकते हैं। हम वादा कर सकते हैं कि हम और हमारे सभी उपवर्ग प्रारंभिक प्रकार के इनिशियलाइज़र को लागू करेंगे, और स्विफ्ट लागू करेंगे (और इसलिए हम सच बता रहे हैं)
protocol Copyable {
init(copy: Self)
}
class C : Copyable {
required init(copy: C) {
}
}
और यह है कि आप प्रतियां कैसे प्रदर्शन करना चाहिए।
हम इसे एक कदम आगे ले जा सकते हैं, लेकिन इसका उपयोग करता है dynamicType
, और मैंने यह सुनिश्चित करने के लिए बड़े पैमाने पर परीक्षण नहीं किया है कि हमेशा वही होता है जो हम चाहते हैं, लेकिन यह सही होना चाहिए:
protocol Copyable {
func copy() -> Self
init(copy: Self)
}
class C : Copyable {
func copy() -> Self {
return self.dynamicType(copy: self)
}
required init(copy: C) {
}
}
यहां हम वादा करते हैं कि एक इनिशलाइज़र है जो हमारे लिए प्रतियां निष्पादित करता है, और फिर हम रनटाइम पर यह निर्धारित कर सकते हैं कि किसे कॉल करना है, हमें वह विधि सिंटैक्स प्रदान करें जिसे आप खोज रहे थे।