2015-08-04 6 views
55

में क्लॉज का उपयोग करके सरणी प्रकारों का विस्तार करें, मैं [फ्लोट] और [डबल] का विस्तार करने के लिए त्वरित फ्रेमवर्क का उपयोग करना चाहता हूं लेकिन इनमें से प्रत्येक को एक अलग कार्यान्वयन की आवश्यकता है।स्विफ्ट

मैं स्पष्ट करने की कोशिश की:

extension Array<Float> { 
} 

और इस त्रुटि मिलती है:

"Constrained extension must be declared on the unspecialised generic type 'Array' with constraints specified by a 'where' clause"

यह इस तरह से सामान्य प्रकार का विस्तार करने स्विफ्ट 2 में posible है?

मुझे कोड अब अपेक्षित के रूप में काम कर रहा है। यहां एक उदाहरण है जो त्वरित रूपरेखा का उपयोग करके एक सारांश दिखा रहा है।

extension _ArrayType where Generator.Element == Float { 

    func quickSum() -> Float { 
     var result: Float = 0 
     if var x = self as? [Float] { 
      vDSP_sve(&x, 1, &result, vDSP_Length(x.count)) 
     } 
     return result 
    } 
} 

extension _ArrayType where Generator.Element == Double { 

    func quickSum() -> Double { 
     var result: Double = 0 
     if var x = self as? [Double] { 
      vDSP_sveD(&x, 1, &result, vDSP_Length(x.count)) 
     } 
     return result 
    } 
} 

उत्तर

87

आप विशिष्ट प्रकार के साथ ही सरणी का विस्तार करना चाहते हैं। आपको _ArrayType प्रोटोकॉल का विस्तार करना चाहिए।

extension _ArrayType where Generator.Element == Int { 

    func doSomething() { 
     ... 
    } 
} 

आप Array का विस्तार यदि आप केवल सुनिश्चित करें कि आपके तत्व किसी और कुछ प्रोटोकॉल पुष्टि कर रहा है कर सकते हैं। अर्थात:

extension Array where Element: Equatable { 

    func doSomething() { 
     ... 
    } 
} 

अपडेट किया गया: स्विफ्ट 3,1https://github.com/apple/swift/blob/master/CHANGELOG.md

extension Array where Element == Int { 

    func doSomething() { 
     ... 
    } 
} 
+0

इससे वास्तव में मुझे थोड़ा अलग समस्या के लिए मदद मिली। मैं ऐरे को ओवरराइड कर रहा था और इसमें शामिल है (तत्व) जो तब तक काम नहीं करता जब तक कि मैंने एलिमेंट के विस्तार को बाधित नहीं किया: Equatable। यह देखने के लिए कि विभिन्न बाधाएं क्या हैं (और वे किन विधियों को प्रभावित करते हैं) SequenceType: http://swiftdoc.org/v2.1/protocol/SequenceType/ –

+0

मुझे लगता है कि आपको '_ArrayType' – Daniel

+8

के बजाय 'अनुक्रम प्रकार' का उपयोग करना चाहिए उत्तर स्विफ्ट 2.2 के साथ पूरी तरह से काम करता है, लेकिन स्विफ्ट 3 में _ArrayType गायब हो गया है। अब हमें यह कैसे करना चाहिए? – Maiaux

14

कैसे

extension CollectionType where Generator.Element == Double { 

} 

के बारे में या आप चाहते हैं थोड़ा और अधिक:

Double और Float या किसी अन्य प्रकार के साथ
protocol ArithmeticType { 
    func +(lhs: Self, rhs: Self) -> Self 
    func -(lhs: Self, rhs: Self) -> Self 
    func *(lhs: Self, rhs: Self) -> Self 
    func /(lhs: Self, rhs: Self) -> Self 
} 

extension Double : ArithmeticType {} 
extension Float : ArithmeticType {} 

extension SequenceType where Generator.Element : protocol<FloatLiteralConvertible, ArithmeticType> { 
    var sum : Generator.Element { 
     return reduce(0.0, combine: +) 
    } 

    var product : Generator.Element { 
     return reduce(1.0, combine: *) 
    } 
} 


stride(from: 1.0, through: 10.0, by: 1.0).sum // 55 
[1.5, 2.0, 3.5, 4.0, 5.5].product    // 231 

वर्क्स कि आप प्रोटोकॉल ArithmeticType और FloatLiteralConvertible के अनुरूप । यदि आपको अपनी सरणी के विशिष्ट सूचकांक तक पहुंचने की आवश्यकता है, तो SequenceType से CollectionType बदलें क्योंकि आप अनुक्रम के साथ ऐसा नहीं कर सकते हैं।

4

इसलिए मैंने सवाल ठीक से नहीं पढ़ा। FloatingPointType एक मौजूदा प्रोटोकॉल है जिसे डबल, फ्लोट और CGFloat द्वारा कार्यान्वित किया गया है, इसलिए

हां। मैंने कल ही सीक्वेंसटाइप में एक फ़ंक्शन जोड़ने के लिए किया था जहां तत्व Equatable होना था। यह Float

पर तत्वों को प्रतिबंधित करने के लिए एक संशोधन है, आपको एक खंड का उपयोग करने की आवश्यकता है। यह नीचे मेरा काम है।

public extension SequenceType where Self.Generator.Element: FloatingPointType 
{ 
    public func splitAt(separator: Generator.Element) -> [[Generator.Element]] 
    { 
     var ret: [[Generator.Element]] = [] 
     var thisPart: [Generator.Element] = [] 

     for element in self 
     { 
      if element == separator 
      { 
       ret.append(thisPart) 
       thisPart = [] 
      } 
      else 
      { 
       thisPart.append(element) 
      } 
     } 
     ret.append(thisPart) 
     return ret 
    } 
} 

[Float(1), Float(2), Float(3), Float(4)].splitAt(Float(2)) 
// returns [[1],[3, 4]] 
[Double(1), Double(2), Double(3), Double(4)].splitAt(Double(3)) 
// returns [[1, 2],[4]] 

नायब मैं एक सरणी के लिए यह काम नहीं कर सके लेकिन SequenceType वैसे भी अधिक सामान्य है।

3

आप केवल Array आप प्रत्येक प्रकार के लिए एक प्रोटोकॉल का उपयोग करने के लिए एक विशिष्ट विस्तार करना चाहते हैं:

protocol DoubleValue { 
    var value: Double { get } 
} 
extension Double: DoubleValue { 
    var value: Double { return self } 
} 
extension Array where Element: DoubleValue { 
    // use the value property 
} 

// the same for Float 
protocol FloatValue { 
    var value: Float { get } 
} 

extension Float: FloatValue { 
    var value: Float { return self } 
} 
extension Array where Element: FloatValue { 
    // use the value property 
} 
27

स्विफ्ट 3 बचाव के लिए !!

extension Collection where Iterator.Element == Int { 
    // `Collection` can be `Sequence`, etc 
} 
+1

यह काम करता है, लेकिन अब मेरे पास संग्रह के लिए सबस्क्रिप्ट तक पहुंच नहीं है। उदाहरण के लिए, यदि मैं 'स्वयं [0]' लिखता हूं, तो मुझे "टाइप प्रकार के एक प्रकार के साथ स्वयं के प्रकार के मूल्य को सब्सक्राइब नहीं किया जा सकता है" त्रुटि – Maiaux

+0

@ मायाउक्स क्योंकि 'सबस्क्रिप्ट' कोई फ़ंक्शन नहीं है और जेनिक्स का समर्थन नहीं करता है, इसलिए मैं अनुमान लगाओ यह बहुत अच्छा काम नहीं करता है। –

+0

कोई अन्य स्विफ्ट 3 समाधान जो सबस्क्रिप्ट का समर्थन करता है? – Maiaux

3

एक्सकोड 8 पर स्विफ्ट 3।2

बस अनुक्रम प्रोटोकॉल का विस्तार करने और एक बयान प्रदान करने की आवश्यकता है।

let someString = "1, 2, 3, 4, 5, 6, 7, 8" 

extension String {   
    func toArrayOfElements() -> [String] { 
    return self.components(separatedBy: ", ") 
    }   
} 

extension Sequence where Iterator.Element == String {   
    func toInt() -> [Int] {    
    return self.map { 
     Int($0)! 
    } 
    }   
} 

let arrayOfStrings = someString.toArrayOfElements()  
print(arrayOfStrings) 

let arrayOfInts = arrayOfStrings.toInt()  
print(arrayOfInts)