Pour être très franc, je suis totalement nouveau pour apprendre la création et l'utilisation d'extensions.
Je voulais créer une catégorie (Extension en Swift 3.0) qui peut être utilisée dans une application pour effectuer des opérations répétées pour Array.
C'est ce que j'ai vu et compris en faisant des recherches, je voulais créer une extension avec différentes méthodes qui devraient être génériques, et non sur la base du type de données nécessaire pour créer des extensions distinctes.
Ici, dans l'exemple ci-dessus, nous devrons créer une seule extension si nous optons pour une extension particulière du type de données. Je voulais avoir un guide s'il existe un moyen de créer la catégorie générique (Extension dans 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...
Remarque: En bref, nous pouvons considérer que je veux effectuer des actions basées sur Array dans une seule extension au lieu de simplement créer l'extension unique pour chacun des types de données conformément à l'exigence ci-dessus.
Comme mentionné dans les commentaires, une façon d'y parvenir est de créer votre propre protocole que les types que vous souhaitez couvrir adoptent (dans les commentaires quelqu'un l'a appelé Content
, utilisé ci-dessous pour cet exemple) (à partir de première 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
}
}
}
Il semble, cependant, que la question d'origine concerne principalement les extensions génériques pour les tableaux, qui, selon un commentaire, ne sont pas possibles mais 100% sont possibles en Swift (c'est un gros Swift, en fait) (de deuxième source ).
Par exemple, si vous souhaitez définir une méthode d'extension spécifique pour Int
s uniquement, vous pouvez le faire:
extension Sequence where Iterator.Element == Int {
var sum: Int {
return reduce(0, +)
}
}
Il semble que les exigences initiales de la question soient des méthodes d'extension qui pourraient être indépendantes du type de données et devraient donc être gardées en commun. Si je comprends bien, il semble cependant que ces types de données ont en général une certaine conformité à Equatable
et/ou Hashable
, qui est l'exigence minimale pour que ce type de générique fonctionne. Cependant, avec la conformité de cet élément, cela est possible en tant que tel:
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.
}
}
La syntaxe Swift change rapidement, et ce qui est ici peut rapidement devenir obsolète, mais ce guide est maintenu assez à jour par Apple et montre la syntaxe la plus récente pour Generics
utilisée ci-dessus ^.
Ma réponse provient d'un couple StackOverflow
questions/réponses, utilisé par exemple/syntaxe ci-dessus ^. Source: (SO Source)(SO Source 2)
En résumé, toutes les méthodes ci-dessus peuvent être combinées, pour une solution d'extension entièrement personnalisée qui a à la fois des fonctions/vars génériques pour tous vos types Array
, tout en ayant des remplacements d'extension spécifiques au type.
Dans la clause where, vous spécifiez "Si le type d'élément a ces règles, considérez cette extension".
Vous n'avez pas besoin d'implémenter toutes les méthodes dans toutes les extensions.
Par exemple:
Vous voulez étendre Array<Element>
Pour avoir généralement la méthode foo(_:Element)
:
extension Array {
func foo(bar: Element) { /*your code goes here */ }
}
Vous souhaitez étendre Array<Element>
Là où Element a implémenté Equatable
(qui inclut Int
, Double
et ... ou toute structure/classe que vous avez marquée comme Equatable
):
extension Array where Element: Equatable {
func find(value: Element) -> Bool {
return index(of: value) != nil
}
}
Vous voulez étendre Sequence
dans les cas où Element
est Numeric
, avoir une somme de variable get-only:
extension Sequence where Element: Numeric {
var sum: Element {
return reduce(0, +)
}
}
Vous souhaitez étendre Collection<Collection<Element: Equatable>>
Pour avoir une méthode à comparer aux collections 2D:
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 }
}
}
Vous n'avez pas besoin d'étendre Array ou collection pour avoir des méthodes comme sort
, find
, etc ... La plupart de ces méthodes sont déjà étendues à l'intérieur du compilateur si votre Element: Equatable
ou Element: Comparable
. en utilisant map
, filter
et reduce
vous pouvez obtenir des structures plus complexes avec peu de code.