हां। लेकिन जवाब थोड़ा अजीब है। पहला भाग समझदार सभ्यता बनाता है; दूसरा हिस्सा सिर्फ पूरी तरह से अजीब है। चलो इसके माध्यम से चलते हैं।
struct Generic<T> {
var args: T
func display() {
print(Printer.print(args))
}
}
सही अधिभार print
के लिए चयन करने के लिए संकलन समय पर निर्णय लिया जाता है, रनटाइम नहीं। यह वह चीज है जो लोगों को सबसे ज्यादा भ्रमित करती है। वे स्विफ्ट को जावास्क्रिप्ट की तरह व्यवहार करना चाहते हैं जहां सब कुछ गतिशील है। स्विफ्ट स्थिर होना पसंद करता है क्योंकि तब यह सुनिश्चित कर सकता है कि आपके प्रकार सही हैं और यह कई अनुकूलन कर सकता है (और स्विफ्ट संकलक अनुकूलन करने के लिए से प्यार करता है)। तो, समय संकलित करें, args
किस प्रकार का है? खैर, यह T
है। T
Printable
होने के लिए जाना जाता है? नहीं ऐसा नहीं है। तो यह गैर-Printable
संस्करण का उपयोग करता है।
लेकिन स्विफ्ट Generic
PrintableObj
का उपयोग करके माहिर हैं, क्या यह उस बिंदु पर नहीं जानता है कि यह Printable
है? संकलक उस बिंदु पर display
का एक अलग संस्करण नहीं बना सका? हां, अगर हम संकलित समय में प्रत्येक कॉलर को जानते थे जो कि इस समारोह के अस्तित्व में होगा, और उनमें से कोई भी कभी भी Printable
(जो कि पूरी तरह से अलग मॉड्यूल में हो सकता है) तक बढ़ाया जाएगा। बहुत सारे अजीब कोने के मामलों (जहां आंतरिक चीजें उदाहरण के लिए सार्वजनिक चीजों की तुलना में अलग-अलग व्यवहार करती हैं) के बिना इसे सुलझाना मुश्किल है, और बिना किसी भविष्य के कॉलर द्वारा display
के हर संभव संस्करण को सक्रिय रूप से उत्पन्न करने के लिए स्विफ्ट को मजबूर किए बिना। समय में स्विफ्ट में सुधार हो सकता है, लेकिन मुझे लगता है कि यह एक कठिन समस्या है। (स्विफ्ट को पहले से ही कुछ प्रदर्शन में कमी का सामना करना पड़ता है ताकि सार्वजनिक जेनेरिक को मूल स्रोत कोड तक पहुंच के बिना विशेषीकृत किया जा सके। इससे यह समस्या और भी जटिल हो जाएगी।)
ठीक है, तो हम इसे प्राप्त करते हैं। T
Printable
नहीं है। लेकिन क्या होगा यदि हमारे पास एक प्रकार था जो अनजाने में Printable
था जिसे हम संकलित समय में जानते थे और इस समारोह के अंदर रहते थे? क्या यह तब काम करेगा?
func display() {
if let p = args as? Printable {
print(Printer.print(p))
} else {
print(Printer.print(args))
}
}
ओह बहुत करीब ... लेकिन काफी नहीं। यह लगभग काम करता है। if-let
वास्तव में वही करता है जो आप करना चाहते हैं। p
असाइन किया जाता है। यह Printable
है। लेकिन यह अभी भी गैर-प्रिंट करने योग्य फ़ंक्शन को कॉल करता है। ?!?!?!?!
यह एक ऐसा स्थान है जहां मैं व्यक्तिगत रूप से सोचता हूं कि स्विफ्ट वर्तमान में टूटा हुआ है और इसकी उम्मीद है कि इसे ठीक किया जाएगा। यह एक बग भी हो सकता है। समस्या यह है कि Printable
स्वयं Printable
के अनुरूप नहीं है। हाँ, मुझे यह नहीं मिला है, लेकिन आप वहां जाते हैं। इसलिए हमें कुछ ऐसा करने की ज़रूरत है जो सही अधिभार प्राप्त करने के लिए Printable
के अनुरूप है। सामान्य रूप से, बचाव के लिए type erasers।
struct AnyPrintable: Printable {
let value: Printable
}
struct Generic<T> {
var args: T
func display() {
if let p = args as? Printable {
print(Printer.print(AnyPrintable(value: p)))
} else {
print(Printer.print(args))
}
}
}
और यह आपके इच्छित तरीके से प्रिंट करेगा। (इस धारणा है कि Printable
कुछ तरीकों की आवश्यकता है पर, आप सिर्फ AnyPrintable
प्रकार रबड़ के लिए उन तरीकों को जोड़ने चाहते हैं।)
बेशक
सही जवाब Printer
में जेनेरिक भार के इस तरह से उपयोग करने के लिए नहीं है। यह बहुत ही भ्रमित और नाजुक तरीका है। यह बहुत अच्छा लग रहा है, लेकिन यह हर समय उड़ाता है।
इस जानकारी के लिए आपको बहुत बहुत धन्यवाद। यह ठीक करने के लिए जटिल लग रहा है कि मैं अभी क्या करने की कोशिश कर रहा हूं। https://github.com/RahulKatariya/Reactofire/blob/develop/ReactofireTests/Models/GenericResponse/_GenericResponse.swift .. मैं जेनेरिक रेस्पॉन्सस्ट्रिंग और जेनेरिक रीस्पॉन्सपर्सन परीक्षण पास करने की कोशिश कर रहा हूं। –
शुभकामनाएं ... मैंने बुनियादी समस्याओं के लिए इस तरह के सुपर-चालाक/जादुई दृष्टिकोणों में बहुत सारे प्रयोग किए। व्यक्तिगत रूप से मैंने पाया कि सरल कोड की कुछ पंक्तियां, भले ही आपको कभी-कभी कुछ कठिन लाइनों को दोहराना पड़ता है, फिर भी बेहतर काम करता है, खासकर जब यह डीबग करने का समय होता है (मैं अभी अपने JSON पार्सिंग को 'गार्ड-लेट' करता हूं; इतना आसान)। यह उतना रोमांचक नहीं है, लेकिन यह मेरी परियोजनाओं में बहुत बेहतर काम करता है। लेकिन उन लोगों के लिए शुभकामनाएं जो अभी भी सीमा की खोज कर रहे हैं! यह मजेदार है, लेकिन इस तरह की बहुत निराशा होती है। –