Расширение типов массивов с помощью предложения where в Swift
Я хотел бы использовать ускоренную структуру для расширения [Float] и [Double], но каждый из них требует другой реализации.
я попробовал очевидное:
extension Array<Float> {
}
и получаю ошибку:
" ограниченное расширение должно быть объявлено на неспециализированном универсальном введите 'Array' с ограничениями, указанными в предложении 'where'"
возможно ли расширить общие типы в Swift 2 таким образом?
Я код работает как ожидается. Вот пример, показывающий суммирование с использованием структуры ускорения.
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
}
}
6 ответов:
если вы хотите расширить только массив с определенным типом. Вы должны расширить протокол _ArrayType.
extension _ArrayType where Generator.Element == Int { func doSomething() { ... } }
если вы расширяете
Array
вы можете только убедиться, что ваш элемент соответствует какой-то другой протокол. я.е:extension Array where Element: Equatable { func doSomething() { ... } }
обновление: С Помощью Swift 3.1https://github.com/apple/swift/blob/master/CHANGELOG.md
extension Array where Element == Int { func doSomething() { ... } }
Swift 3 на помощь!!
extension Collection where Iterator.Element == Int { // `Collection` can be `Sequence`, etc }
как о
extension CollectionType where Generator.Element == Double { }
или если вы хотите немного подробнее:
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
работает с
Double
иFloat
или любой другой тип, который вам соответствует протоколамArithmeticType
иFloatLiteralConvertible
. Если вам нужно получить доступ к определенным индексам массива, изменениеSequenceType
доCollectionType
как вы не можете сделать это с последовательностью.
так что я не читал вопрос правильно.
FloatingPointType
- это существующий протокол, который реализуется с помощью Double, Float и CGFloat, так чтода. Я сделал это только вчера, чтобы добавить функцию в SequenceType, где элементы должны были быть
Equatable
. Это модификация, чтобы ограничить элементыFloat
вы должны использовать предложение where. Это моя функция ниже.
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]]
NB я не мог сделать эту работу для массива, но SequenceType является более общим в любом случае.
Swift 3 на Xcode 8.2
просто нужно расширить протокол последовательности и предоставить оператор where.
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()! } } } let arrayOfStrings = someString.toArrayOfElements() print(arrayOfStrings) let arrayOfInts = arrayOfStrings.toInt() print(arrayOfInts)
Если вы хотите расширить возможности
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 }