2015-06-24 6 views
9

के लिए में जहां मैं इस परिदृश्य:Typecasting और पाश

protocol A {} 
protocol B: A {} 
protocol C: A {} 

let objects: [A] = ... 

कैसे कर सकते हैं मैं सरणी के माध्यम से पाश और केवल वस्तुओं है कि प्रकार B के हैं के लिए तर्क को अंजाम?

अभी, मैं कुछ इस तरह कर रहा हूँ:

for object in objects { 
    if let b = object as? B { 
     ... 
    } 
} 

लेकिन अगर मैं इस अधिक अर्थपूर्ण और सुरुचिपूर्ण बनाने के लिए where उपयोग कर सकते हैं मैं सोच रहा था।

for b in objects where b is B // <- compiles, but b is typed as A, not B 
for b: B in objects where b is B // <- doesn't compile 
for b in objects as! [B] where b is B // <- I get a warning that "is" will always be true 

उत्तर

8

वहाँ भी for case है (लगभग एक ही caseswitch बयान के रूप में) तो यह इस प्रकार दिखाई देगा:

for case let b as B in objects { 
    // use b which is now of type B 
} 

एक और अच्छा अभिव्यक्ति है:

for case let b as protocol<B, C> in objects { 
    // use b which is now of type protocol<B, C> 
} 

ताकि आप तरीकों का उपयोग कर सकते हैं, गुण और एक ही समय में दोनों प्रोटोकॉल से

0

मैं 100% कुछ नहीं है कि यह अपने मामले का उत्तर देता हूँ - क्योंकि आप कुछ इसी तरह पहले से ही है - और मैं पूरी तरह से समझ में नहीं आता है कि आप अपने संस्करण के बारे में पसंद नहीं है क्या। हालांकि इस स्विफ्ट 2 में काम करता है:

for object in objectArray where object is protocolB { 
    //print(object) // only objects conforming to protocolB 
} 

यहाँ मेरी घोषणाओं हैं:

var objectArray: [AnyObject] = [] 
// contains a mix of objects of the following 3 classes 


class class01: protocolA { 
} 
class class02: protocolA, protocolB { 
    func test() -> String { 
    // required to conform to protocolB 
    return "hello" 
    } 
} 
class class03: protocolA, protocolB, protocolC { 
    func test() -> String { 
    // required to conform to protocolB 
    return "hello" 
    } 
} 

protocol protocolA { 
} 
protocol protocolB: protocolA { 
    func test() -> String 
} 
protocol protocolC: protocolA { 
} 

compiles, लेकिन ख एक के रूप में लिखा गया हो,

बी नहीं कि थोड़ा मैं डॉन है 't समझ। अधिकतर संभावना है क्योंकि मैं गूंगा हूं। लेकिन जिस तरह से मैं इसे पढ़ रहा हूं, आपकी प्रोटोकॉलबी ऑब्जेक्ट्स प्रोटोकॉल के अनुरूप भी परिभाषित हैं। मैंने इसे वही परिभाषित किया है।

+0

यदि 'प्रोटोकॉल बी' फ़ंक्शन 'टेस्ट() 'को परिभाषित करेगा, तो आप' ऑब्जेक्ट 'को' प्रोटोकॉलबी 'टाइप किए बिना' ऑब्जेक्ट 'पर अपने ऑब्जेक्ट में कॉल नहीं कर पाएंगे, क्योंकि' ऑब्जेक्ट 'प्रकार का है 'AnyObject', प्रकार 'प्रोटोकॉल बी' प्रकार नहीं है। – rid

+0

अपडेट किए गए कोड में, यदि आप लूप में 'प्रिंट (object.test())' कॉल करने का प्रयास करते हैं, तो आपको एक त्रुटि मिलेगी ('AnyObject' के पास 'test()' नामक सदस्य नहीं है)। – rid

+0

यह एक्सकोड 7 में बिल्कुल ठीक काम करता है। 'प्रिंट (ऑब्जेक्ट) 'सहित। यह केवल टिप्पणी की गई थी क्योंकि यह एक उदाहरण था – simons

2

as? subtype और इसके संस्करण टीएस एक कोड गंध हैं। यहां दिए गए अन्य उत्तर आपको जो भी चाहते हैं उसे पूरा करने में मदद करेंगे, लेकिन मैं यह सुझाव देना चाहता हूं कि आप इस तर्क को प्रोटोकॉल पर for लूप से ले जाएं (यदि यह संभव है)।

:

struct Circle : Shape { 
    func draw() { 
     // drawing code goes here 
    } 
} 

struct Diamond : Shape { 
    func draw() { 
     // drawing code goes here 
    } 
} 

struct Pentagon : Shape { 
    func draw() { 
     // drawing code goes here 
    } 

    func executeSomeSpecialOperation() { 
     print("I'm a pentagon!") 
    } 
} 

आप जानते हैं, आप आकार की एक सरणी बना सकते हैं:

protocol Shape { 
    func draw() 
    func executeSomeSpecialOperation() 
} 

extension Shape { 
    func executeSomeSpecialOperation() { 
     // do nothing by default 
    } 
} 

तीन आकार प्रकार है कि यह के अनुरूप बनाएं:

उदाहरण के लिए, एक Shape प्रोटोकॉल पर विचार

let shapes : [Shape] = [Circle(), Diamond(), Pentagon()] 

यह दृष्टिकोण आपको इस प्रकार के बिना अपना प्रकार जानने के बिना लूप देता है:

for shape in shapes { 
    shape.draw() 
    shape.executeSomeSpecialOperation() 
} 

यह दो लाभ हैं:

  • कम कर देता है युग्मन
  • सामंजस्य (Pentagon से संबंधित तर्क बढ़ जाती है (अपने विधि for पाश चल पता है कि एक Pentagon है की जरूरत नहीं है) निहित है उस प्रकार की परिभाषा के भीतर)

मुझे यह सुनिश्चित नहीं है कि यह आपके विशिष्ट उपयोग मामले के लिए काम करेगा, लेकिन मैं वें स्याही यह आमतौर पर एक बेहतर पैटर्न है।

+0

यह मानता है कि विधि सभी 'आकार' के लिए समझ में आता है। उदाहरण के लिए आप क्या करेंगे यदि आप 'आकार' सरणी में सभी मंडलियों के औसत त्रिज्या की गणना करना चाहते हैं? – rid

+0

अगर मैं homogeny पर निर्भर संचालन करने की जरूरत है तो मैं एक सरणी में विषम प्रकारों को स्टोर नहीं करता। उदाहरण के लिए, आप एक अलग 'मंडल' सरणी बना सकते हैं, और 'आकार' को एक गणना की गई संपत्ति बना सकते हैं। –

+0

तो हर बार जब आपको सभी आकारों की एक सूची की आवश्यकता होती है, तो एक नई सरणी तुरंत चालू की जाएगी? – rid