2014-11-11 4 views
15
में एक प्रोटोकॉल के अनुरूप प्रकार के किसी सरणी नहीं बना सकता

मैं निम्नलिखित प्रोटोकॉल और एक वर्ग है कि यह के अनुरूप है:स्विफ्ट

protocol Foo{ 
    typealias BazType 

    func bar(x:BazType) ->BazType 
} 


class Thing: Foo { 
    func bar(x: Int) -> Int { 
     return x.successor() 
    } 
} 

जब मैं कम महत्वपूर्ण चीज़ें के एक सरणी बनाने का प्रयास करें, मैं एक मिल अजीब त्रुटि:

var foos: Array<Foo> = [Thing()] 

Protocol Foo can only be used as a generic constraint because it has Self or associated type requirements.

ठीक है, तो यह केवल अगर यह एक संबद्ध प्रकार आवश्यकता (जो यह करता है) है, लेकिन किसी कारण से यह एक त्रुटि है इस्तेमाल किया जा सकता ?? WTF ?!

मुझे यकीन है कि मैं पूरी तरह से समझते क्या संकलक मुझे बताने की कोशिश कर रहा है नहीं कर रहा हूँ ...

+0

के संभावित डुप्लिकेट (http://stackoverflow.com/questions/26267597/cannot-assign-class-instance-to -ट्स-प्रोटोकॉल-प्रकार) – Antonio

उत्तर

13

मान लीजिए, अगर हम सरणी foos में Thing का एक उदाहरण डाल सकता है, तो क्या होगा?

protocol Foo { 
    typealias BazType 

    func bar(x:BazType) -> BazType 
} 

class Thing: Foo { 
    func bar(x: Int) -> Int { 
     return x.successor() 
    } 
} 

class AnotherThing: Foo { 
    func bar(x: String) -> String { 
     return x 
    } 
} 

var foos: [Foo] = [Thing()] 

AnotherThingFoo भी अनुरूप है क्योंकि, इसलिए हम इसे foos में भी डाल सकते हैं।

foos.append(AnotherThing()) 

अब हम foos बेतरतीब ढंग से एक foo हड़पने।

let foo = foos[Int(arc4random_uniform(UInt32(foos.count - 1)))] 

और मैं विधि bar कॉल करने के लिए जा रहा हूँ, क्या आप मुझे बता सकते हैं कि मैं एक स्ट्रिंग या bar को एक पूर्णांक भेजना चाहिए?

foo.bar("foo") या foo.bar(1)

स्विफ्ट नहीं कर सकता।

तो इसे केवल सामान्य बाधा के रूप में उपयोग किया जा सकता है।

इस परिदृश्य के लिए इस परिदृश्य की आवश्यकता क्या है?

उदाहरण: [? इसके प्रोटोकॉल प्रकार के वर्ग उदाहरण आवंटित नहीं किया जा सकता]

class MyClass<T: Foo> { 
     let fooThing: T? 

     init(fooThing: T? = nil) { 
       self.fooThing = fooThing 
     } 

     func myMethod() { 
       let thing = fooThing as? Thing // ok 
       thing?.bar(1) // fine 

       let anotherThing = fooThing as? AnotherThing // no problem 
       anotherThing?.bar("foo") // you can do it 

       // but you can't downcast it to types which doesn't conform to Foo 
       let string = fooThing as? String // this is an error 
     } 
} 
1

मैं अपने कोड को समझने के लिए प्रोटोकॉल को लागू करने की कोशिश कर के साथ खेल रहे हैं। मैंने पाया कि आप टाइपियास को सामान्य प्रकार के रूप में उपयोग नहीं कर सकते क्योंकि यह केवल एक उपनाम है जो स्वयं ही एक प्रकार का नहीं है। तो यदि आप अपने प्रोटोकॉल और अपनी कक्षा के बाहर टाइपियास घोषित करते हैं तो आप बिना किसी समस्या के अपने कोड में इसका प्रभावी ढंग से उपयोग कर सकते हैं।

नोट: Typealias अपनी घोषणा में Int प्रकार, इस तरह आप हमेशा इंट प्रकार के बजाय अन्य नाम का उपयोग और इससे संबंधित तरीकों और कार्यों के सभी का उपयोग कर सकते है।

यहाँ मैं कैसे यह काम कर:

typealias BazType = Int 

protocol Foo{ 
    func bar(x:BazType) -> BazType 
} 

class Thing: Foo { 
    func bar(x: BazType) -> BazType { 
    return x.successor() 
    } 
} 

let elements: Array<Foo> = [Thing(), Thing()] 
+0

इस कोड में BazType सिर्फ Int है और एक चर प्रकार नहीं है। –