मैं प्रोटोकॉल का उपयोग करके वस्तुओं के दृढ़ता से टाइप किए गए पदानुक्रम को डिजाइन करने की कोशिश कर रहा हूं, लेकिन यह बिल्कुल सही नहीं हो सकता है।

उदाहरण के लिए, मान लीजिए कि इन प्रोटोकॉल को अपनाने वाले ठोस प्रकार हैं वर्ग Country, State, और City

प्रत्येक नोड में माता-पिता (रूट ऑब्जेक्ट को छोड़कर) और/या बच्चे (पत्ती वस्तुओं को छोड़कर) हो सकते हैं: सभी State उदाहरण एकल Country उदाहरण के बच्चे हैं और इसे माता-पिता के रूप में रखते हैं, और उनके पास है City बच्चों के रूप में उदाहरण, आदि।

तो मैं इन दो प्रोटोकॉल से शुरू करता हूं:

/// To be adopted by State and City
///
protocol Child: AnyObject {
    associatedtype ParentType: AnyObject 
    // (-> so that property `parent` can be weak)

    weak var parent: ParentType? { get }
} 

/// To be adopted by Country and State
///
protocol Parent: AnyObject {
    associatedtype ChildType: AnyObject
    // (-> for symmetry)

    var children: [ChildType] { get }
}

मेरे पास एक के बजाय दो अलग-अलग प्रोटोकॉल हैं जो उपरोक्त सभी आवश्यकताओं को समूहित करते हैं, क्योंकि मैं रूट क्लास Country के लिए "डमी" typealias ParentType निर्दिष्ट नहीं करना चाहता हूं। (जो अर्थहीन है), न ही लीफ क्लास City के लिए "डमी" typealias ChildType

इसके बजाय, मैं माता-पिता और बच्चे के व्यवहार को अलग कर सकता हूं और केवल मध्यवर्ती वर्ग State को दोनों प्रोटोकॉल अपनाने के लिए कह सकता हूं।


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

protocol UnarchivableChild: Child {
    init(dictionary: [String: Any], parent: ParentType?)
}

protocol UnarchivingParent: Parent {
    associatedtype ChildType: UnarchivableChild

    func readChildren(fromDictionaries dictionaries: [[String: Any]]) -> [ChildType]
}

जैसा कि यह खड़ा है, ऐसा लगता है कि मैं एक कदम आगे जा सकता हूं और इस तरह readChildren(fromDictionaries:) विधि का डिफ़ॉल्ट कार्यान्वयन जोड़ सकता हूं:

extension UnarchivingParent {
    func readChildren(fromDictionaries dictionaries: [[String: Any]]) -> [ChildType] {
        return dictionaries.flatMap({ dictionary in
            return ChildType(dictionary: dictionary, parent: self)
        })
    }
}

...क्योंकि इस प्रोटोकॉल में, ChildType UnarchivableChild तक सीमित है, इसलिए इसे इनिशियलाइज़र का समर्थन करना चाहिए...? लेकिन मुझे मिलता है:

प्रकार की तर्क सूची के साथ 'चाइल्ड टाइप' का आह्वान नहीं कर सकता '(शब्दकोश: ([स्ट्रिंग: कोई भी]), माता-पिता: स्वयं)'

(बड़े अक्षरों में "स्वयं" क्यों?)

मुझे लगता है कि मुझे कुछ याद आ रहा है कि कैसे संबंधित प्रकार काम करते हैं ...

मैं इस डिफ़ॉल्ट कार्यान्वयन को कैसे कोडित कर सकता हूं?


अपडेट: जाहिरा तौर पर, स्वयं को पास करना किसी भी तरह से समस्या है। मैंने कोड को इसमें संशोधित किया:

protocol Node: AnyObject {
}

protocol Parent: Node {
    associatedtype ChildNodeType: Node
    var children: [ChildNodeType] { get set }
}

protocol Child: Node {
    associatedtype ParentNodeType: Node
    weak var parent: ParentNodeType? { get set }
}

protocol UnarchivableChild: Child {
    init(dictionary: [String: Any]) // Removed parent parameter!
}

protocol UnarchivingParent: Parent {
    associatedtype ChildNodeType: UnarchivableChild
    func readChildren(fromDictionaries dictionaries: [[String: Any]]) -> [ChildNodeType]
}

extension UnarchivingParent {
    func readChildren(fromDictionaries dictionaries: [[String: Any]]) -> [ChildNodeType] {
        return dictionaries.flatMap({
            let child = ChildNodeType(dictionary: $0)
            // Assign parent here instead:
            child.parent = self // < ERROR HERE

            return child
        })
    }
} 

त्रुटि है:

'_?' टाइप करने के लिए 'स्व' प्रकार का मान निर्दिष्ट नहीं कर सकता

0
Nicolas Miari 7 सितंबर 2017, 12:59

1 उत्तर

सबसे बढ़िया उत्तर

The Swift Programmng Language: Generics (अनुभाग: "Extensions with a Generci जहां क्लॉज"), मुझे जो चाहिए था उसे हासिल करने के लिए मुझे उपयुक्त सिंटैक्स मिला। मैं इस कोड के लिए बस गया (प्रकार के नाम मूल प्रश्न में थोड़े भिन्न रूप हैं):

protocol DictionaryInitializable {
    init(dictionary: [String: Any])
}

protocol ChildNode: AnyObject {
    associatedtype ParentType: AnyObject

    weak var parent: ParentType? { get set }
}

protocol ParentNode {
    associatedtype ChildType: AnyObject

    var children: [ChildType] { get set }
}

// This 'WHERE' clause fixes the issue:
extension ParentNode where ChildType: DictionaryInitializable,
ChildType: ChildNode, ChildType.ParentType == Self {

    func readChildren(from dictionaries: [[String: Any]]) -> [ChildType] {
        return dictionaries.map({
            return ChildType(dictionary: $0)
        })
    }
}

जहां क्लॉज की पहली बाधा मुझे इनिशियलाइज़र init(dictionary:) को कॉल करने देती है, दूसरा एक प्रॉपर्टी parent की उपस्थिति की गारंटी देता है, और तीसरा मुझे इसके मूल्य के रूप में self असाइन करने देता है।

वैकल्पिक रूप से, मैं बदल सकता हूं:

protocol ParentNode {
    associatedtype ChildType: AnyObject

प्रति:

protocol ParentNode {
    associatedtype ChildType: ChildNode

... और दूसरी बाधा छोड़ें।

0
Nicolas Miari 8 सितंबर 2017, 05:03