To be very frank, I am totally new to learn Extension creation and usage.
I wanted to create a category (Extension in swift 3.0) which can be used throughout an application to perform repeated operations for Array.
Sample Link 1
This is what I have seen and understand while doing research, I wanted to create an extension with various methods which should be generic, and not on the basis of datatype needed to create separate extensions.
Here in above example, we will need to create single extension if we will go for particular datatype wise extension. I wanted to have a guidance if any way is there to create the generic category (Extension in swift).
extension _ArrayType where Generator.Element == Int
extension Array where Element: Equatable
extension Array where Element == Int
extension _ArrayType where Generator.Element == Float
extension SequenceType where Self.Generator.Element: FloatingPointType
extension Array where Element: DoubleValue
extension Sequence where Iterator.Element == String
,etc...
Sample Link 2
Note : In short, we can consider that I want to perform actions based on Array in single extension instead of just creating the single extension for each of the datatypes as per above requirement.
Extensions add new functionality to an existing class, structure, enumeration, or protocol type. This includes the ability to extend types for which you don't have access to the original source code (known as retroactive modeling). Extensions are similar to categories in Objective-C.
For example: var myArray = [Foo]() means that myArray will only contain type Foo . Foo in this case is "mapped" to the generic placeholder Element . If you want to change the general behavior of Array (via extension) you would use the generic placeholder Element and not any concrete type (like Foo).
In Swift, we can add new functionality to existing types. We can achieve this using an extension. Here, we have created an extension of the Temperature class using the extension keyword. Now, inside the extension, we can add new functionality to Temperature .
As mentioned in the comments, one way to accomplish this is to create your own protocol that the types you want to cover adopt (in the comments someone called it Content
, used below for this example) (from first source):
protocol Content {
var hash: String { get }
}
extension Array where Element : Content {
func filterWithId(id : String) -> [Element] {
return self.filter { (item) -> Bool in
return item.id == id
}
}
}
It seems, though, that the original question is mainly asking about generic extensions for arrays, which one comment says are not possible but 100% are possible in Swift (it's a big Swift feature, actually) (from second source).
For example, if you want to define a specific extension method for Int
s only, you can do that:
extension Sequence where Iterator.Element == Int {
var sum: Int {
return reduce(0, +)
}
}
It seems like the question's original requirements are extension methods that could be agnostic to data type and therefore should be kept in common. If I understand correctly, seems though that these data types in general have some conformance to Equatable
and/or Hashable
, which is the minimum requirement for this kind of generic-stuff to work. With this element conformance, though, this is possible as such:
extension Sequence where Iterator.Element is Equatable {
func extensionMethodName<T: Equatable>(_ input: [T], singleElement: T) -> [T] {
// T is now a generic array of equatable items. You can implement whatever extension logic you need with these.
// I added different ways of passing in and returning this generic type, but the only thing that is likely going to be consistent is the `<T: Equatable>` which is Swift standard syntax for declaring generic type parameters for a method.
}
}
The Swift syntax changes quickly, and what's here can quickly go out of date, but this guide is kept fairly up-to-date by Apple and shows the most up to date syntax for Generics
used above ^.
My answer pulls from a couple StackOverflow
questions/answers, used for example/syntax above ^. Source: (SO Source) (SO Source 2)
In summary, all the methods above can be combined, for a fully custom extension solution that has both generic functions/vars for all your Array
types, while still having type-specific extension overrides.
In where clause, you specify "If the Element type has these rules, consider this extension".
You don't need to implement all of the methods in all extensions.
For example:
You want to extend Array<Element>
to generally have method foo(_:Element)
:
extension Array {
func foo(bar: Element) { /*your code goes here */ }
}
You want to extend Array<Element>
where Element did implement Equatable
(which includes Int
,Double
and ... or any structs/classes you've marked as Equatable
):
extension Array where Element: Equatable {
func find(value: Element) -> Bool {
return index(of: value) != nil
}
}
You want to extend Sequence
in cases that Element
is Numeric
, have get-only variable sum:
extension Sequence where Element: Numeric {
var sum: Element {
return reduce(0, +)
}
}
You want to extend Collection<Collection<Element: Equatable>>
to have a method to compare to 2D Collections:
extension Collection
where Iterator.Element: Collection,
Iterator.Element.Iterator.Element: Equatable {
func compare(to: Self) -> Bool {
let flattenSelf = self.reduce([], +)
let flattenTo = to.reduce([], +)
return flattenSelf.count == flattenTo.count &&
zip(flattenSelf, flattenTo).reduce(true) { $0 && $1.0 == $1.1 }
}
}
You don't need to extend Array or collection to have methods like sort
, find
, etc... Most of these methods are already extended inside the compiler if your Element: Equatable
or Element: Comparable
. using map
, filter
and reduce
you can achieve more complex structures with not much of a code.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With