स्विफ्ट में कई प्रकार की बाधाएं


133

मान लीजिए कि मेरे पास ये प्रोटोकॉल हैं:

protocol SomeProtocol {

}

protocol SomeOtherProtocol {

}

अब, अगर मुझे एक ऐसा फंक्शन चाहिए जो एक जेनेरिक टाइप ले, लेकिन उस टाइप को SomeProtocolमेरे अनुरूप होना चाहिए :

func someFunc<T: SomeProtocol>(arg: T) {
    // do stuff
}

लेकिन क्या कई प्रोटोकॉल के लिए एक प्रकार की बाधा जोड़ने का एक तरीका है?

func bothFunc<T: SomeProtocol | SomeOtherProtocol>(arg: T) {

}

इसी तरह की चीजें कॉमा का उपयोग करती हैं, लेकिन इस मामले में, यह एक अलग प्रकार की घोषणा शुरू करेगा। यहाँ मैंने कोशिश की है।

<T: SomeProtocol | SomeOtherProtocol>
<T: SomeProtocol , SomeOtherProtocol>
<T: SomeProtocol : SomeOtherProtocol>

यह एक विशेष रूप से प्रासंगिक सवाल है क्योंकि स्विफ्ट डॉक्स ने जेनरिक अध्याय में इसका उल्लेख नहीं किया है ...
ब्रूनो फिलिप

जवाबों:


241

आप एक ऐसे क्लॉज का उपयोग कर सकते हैं, जो आपको जितनी चाहें उतनी आवश्यकताओं को निर्दिष्ट करने देता है (सभी को पूरा करना होगा) अल्पविराम द्वारा अलग किया गया

स्विफ्ट 2:

func someFunc<T where T:SomeProtocol, T:SomeOtherProtocol>(arg: T) {
    // stuff
}

स्विफ्ट 3 और 4:

func someFunc<T: SomeProtocol & SomeOtherProtocol>(arg: T) {
    // stuff
}

या अधिक शक्तिशाली जहां खंड:

func someFunc<T>(arg: T) where T:SomeProtocol, T:SomeOtherProtocol{
    // stuff
}

आप निश्चित रूप से प्रोटोकॉल संरचना (जैसे protocol<SomeProtocol, SomeOtherProtocol>) का उपयोग कर सकते हैं , लेकिन यह थोड़ा कम लचीला है।

का उपयोग करते हुए whereआप ऐसे मामलों में जहां कई प्रकार के शामिल कर रहे हैं के साथ सौदा कर सकते हैं।

आप अभी भी कई स्थानों पर पुन: उपयोग के लिए प्रोटोकॉल बनाना चाहते हैं, या केवल बनाये गए प्रोटोकॉल को एक सार्थक नाम दे सकते हैं।

स्विफ्ट 5:

func someFunc(arg: SomeProtocol & SomeOtherProtocol) { 
    // stuff
}

यह अधिक स्वाभाविक लगता है क्योंकि प्रोटोकॉल तर्क के बगल में हैं।


Geez यह तर्कसंगत नहीं है, लेकिन यह जानने के लिए अच्छा है कि मैं सिर्फ इस एक के लिए धन्यवाद spammers में से एक बनना चाहता हूं, havent 'यह एक महीने में एहसास हुआ क्योंकि मुझे इसकी आवश्यकता थी।
मैथिज्स सीजर

3
किसी भी तरह के वर्ग अभिव्यक्ति के साथ कक्षाओं और संरचनाओं के साथ एक ही काम करने का कोई तरीका है? जैसे <T where T:SomeStruct, T:AnotherStruct>? संकलक के लिए संकलक यह व्याख्या करते हुए कहता है कि "T दोनों का उपवर्ग है", और संरचना के लिए यह केवल शिकायत करता है "Type 'T' constrained to non-protocol type"
जारोद स्मिथ

ओपी में विशिष्ट उदाहरण के लिए: प्रश्न प्रोटोकॉल रचना बेहतर तरीका होना चाहिए : उपरोक्त समाधान मान्य है, लेकिन, imho, अनावश्यक रूप से फ़ंक्शन हस्ताक्षर का सुराग लगाता है। इसके अलावा, प्रोटोकॉल संरचना का उपयोग करना, जैसे, एक प्रकार की बाधा, फिर भी आप whereअतिरिक्त प्रकार / अन्य उपयोग के func someFunc<U, T: protocol<SomeProtocol, SomeOtherProtocol> where T.SubType == U>(arg: T, arg2: U) { ... }लिए क्लॉज का उपयोग कर सकते हैं, उदाहरण के लिए टाइपेलियास SubTypeके लिए SomeProtocol
d

1
ऐसा लगता है कि स्विफ्ट 3 में अपग्रेड किया गया है और उपयोग करने की सिफारिश की गई है: func someFunc <T> (arg: T) जहां T: SomeProtocol, T: SomeOtherProtocol {
Cristi Băluosă

2
क्या स्विफ्ट को बताने का एक तरीका है कि टी को एक निश्चित ऑब्जेक्ट प्रकार का होना चाहिए और एक निश्चित प्रोटोकॉल को लागू करना होगा?
जॉर्ज

73

आपके पास दो संभावनाएँ हैं:

  1. जियारो के उत्तर में दिए गए संकेत के अनुसार आप एक क्लॉज का उपयोग करते हैं :

    func someFunc<T where T : SomeProtocol, T : SomeOtherProtocol>(arg: T) {
        // do stuff
    }
  2. आप एक प्रोटोकॉल संरचना प्रकार का उपयोग करते हैं :

    func someFunc<T : protocol<SomeProtocol, SomeOtherProtocol>>(arg: T) {
        // do stuff
    }

2
imo दूसरा समाधान प्रेटीयर है, मैं इस उत्तर के लिए जाऊंगा यह दो विकल्पों को प्रस्तुत करने के लिए भी अधिक पूर्ण है
Mathijs Segers

2
नंबर 2 केवल एक है जो स्विफ्ट 2 के तहत मेरे लिए काम करता है जब एक की घोषणा करता है typealias। धन्यवाद!
ब्रूनो फिलिप

19

3.0 स्विफ्ट के विकास में कुछ बदलाव आए। हमारे दो विकल्प अब अलग दिखते हैं।

whereस्विफ्ट 3.0 में एक क्लॉज का उपयोग करना :

whereखंड अब पठनीयता में सुधार करने के लिए एक समारोह हस्ताक्षर के अंत में ले जाया गया। अब एकाधिक प्रोटोकॉल वंशानुक्रम इस तरह दिखता है:

func someFunc<T>(arg: T) where T:SomeProtocol, T:SomeOtherProtocol {

}

protocol<>स्विफ्ट 3.0 में निर्माण का उपयोग करना :

protocol<>निर्माण का उपयोग करने वाली संरचना को अपदस्थ किया जा रहा है। पहले protocol<SomeProtocol, SomeOtherProtocol>अब इस तरह दिखता है:

func someFunc<T:SomeProtocol & SomeOtherProtocol>(arg: T) {

}

संदर्भ।

इन परिवर्तनों के बारे में अधिक जानकारी whereयहाँ हैं: https://github.com/apple/swift-evolution/blob/master/proposals/0081-move-where-expression.md

और, प्रोटोकॉल के लिए परिवर्तनों पर अधिक <> निर्माण यहां हैं: https://github.com/apple/swift-evolution/blob/master/proposals/0095-any-as-existential.md


13

स्विफ्ट 3 आपके फ़ंक्शन को घोषित करने के लिए 3 अलग-अलग तरीके प्रदान करता है।

protocol SomeProtocol {
    /* ... */
}

protocol SomeOtherProtocol {
    /* ... */        
}

1. &ऑपरेटर का उपयोग करना

func someFunc<T: SomeProtocol & SomeOtherProtocol>(arg: T) {
    /* ... */
}

2. whereक्लॉज का उपयोग करना

func someFunc<T>(arg: T) where T: SomeProtocol, T: SomeOtherProtocol {
    /* ... */
}

3. whereक्लॉज और &ऑपरेटर का उपयोग करना

func someFunc<T>(arg: T) where T: SomeProtocol & SomeOtherProtocol {
    /* ... */        
}

यह भी ध्यान दें कि आप typealiasअपने फ़ंक्शन घोषणा को छोटा करने के लिए उपयोग कर सकते हैं ।

typealias RequiredProtocols = SomeProtocol & SomeOtherProtocol

func someFunc<T: RequiredProtocols>(arg: T) {
    /* ... */   
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.