( Swift 2.x )
Vous pouvez également étendre le tableau pour qu'il soit conforme à un protocole contenant des plans directeurs pour les méthodes de type générique, par exemple, un protocole contenant vos utilitaires fonctionnels personnalisés pour tous les éléments de tableau génériques conformes à une contrainte de type, par exemple le protocole MyTypes
. L'avantage de cette approche est que vous pouvez écrire des fonctions en prenant des arguments de tableau génériques, avec une contrainte que ces arguments de tableau doivent être conformes à votre protocole d'utilitaires de fonctions personnalisés, par exemple le protocoleMyFunctionalUtils
.
Vous pouvez obtenir ce comportement soit implicitement, en saisissant les éléments du tableau sous contrainte MyTypes
, soit --- comme je vais le montrer dans la méthode que je décris ci-dessous ---, de manière assez claire et explicite, en laissant votre en-tête de fonctions de tableau générique montrer directement que les tableaux d'entrée conforme à MyFunctionalUtils
.
Nous commençons par les protocoles MyTypes
à utiliser comme contrainte de type; étendre les types que vous souhaitez adapter à vos génériques par ce protocole (l'exemple ci-dessous étend les types fondamentaux Int
et Double
ainsi qu'un type personnalisé MyCustomType
)
/* Used as type constraint for Generator.Element */
protocol MyTypes {
var intValue: Int { get }
init(_ value: Int)
func *(lhs: Self, rhs: Self) -> Self
func +=(inout lhs: Self, rhs: Self)
}
extension Int : MyTypes { var intValue: Int { return self } }
extension Double : MyTypes { var intValue: Int { return Int(self) } }
// ...
/* Custom type conforming to MyTypes type constraint */
struct MyCustomType : MyTypes {
var myInt : Int? = 0
var intValue: Int {
return myInt ?? 0
}
init(_ value: Int) {
myInt = value
}
}
func *(lhs: MyCustomType, rhs: MyCustomType) -> MyCustomType {
return MyCustomType(lhs.intValue * rhs.intValue)
}
func +=(inout lhs: MyCustomType, rhs: MyCustomType) {
lhs.myInt = (lhs.myInt ?? 0) + (rhs.myInt ?? 0)
}
Protocole MyFunctionalUtils
(contenant les plans de nos utilitaires de fonctions de tableau génériques supplémentaires) et par la suite, l'extension de Array par MyFunctionalUtils
; mise en œuvre de méthodes imprimées en bleu:
/* Protocol holding our function utilities, to be used as extension
o Array: blueprints for utility methods where Generator.Element
is constrained to MyTypes */
protocol MyFunctionalUtils {
func foo<T: MyTypes>(a: [T]) -> Int?
// ...
}
/* Extend array by protocol MyFunctionalUtils and implement blue-prints
therein for conformance */
extension Array : MyFunctionalUtils {
func foo<T: MyTypes>(a: [T]) -> Int? {
/* [T] is Self? proceed, otherwise return nil */
if let b = self.first {
if b is T && self.count == a.count {
var myMultSum: T = T(0)
for (i, sElem) in self.enumerate() {
myMultSum += (sElem as! T) * a[i]
}
return myMultSum.intValue
}
}
return nil
}
}
Enfin, des tests et deux exemples montrant une fonction prenant des tableaux génériques, avec respectivement les cas suivants
Montrant l' assertion implicite que les paramètres du tableau sont conformes au protocole «MyFunctionalUtils», via le type contraignant les éléments du tableau à «MyTypes» (fonction bar1
).
Montrant explicitement que les paramètres du tableau sont conformes au protocole 'MyFunctionalUtils' (fonction bar2
).
Le test et les exemples suivants:
/* Tests & examples */
let arr1d : [Double] = [1.0, 2.0, 3.0]
let arr2d : [Double] = [-3.0, -2.0, 1.0]
let arr1my : [MyCustomType] = [MyCustomType(1), MyCustomType(2), MyCustomType(3)]
let arr2my : [MyCustomType] = [MyCustomType(-3), MyCustomType(-2), MyCustomType(1)]
/* constrain array elements to MyTypes, hence _implicitly_ constraining
array parameters to protocol MyFunctionalUtils. However, this
conformance is not apparent just by looking at the function signature... */
func bar1<U: MyTypes> (arr1: [U], _ arr2: [U]) -> Int? {
return arr1.foo(arr2)
}
let myInt1d = bar1(arr1d, arr2d) // -4, OK
let myInt1my = bar1(arr1my, arr2my) // -4, OK
/* constrain the array itself to protocol MyFunctionalUtils; here, we
see directly in the function signature that conformance to
MyFunctionalUtils is given for valid array parameters */
func bar2<T: MyTypes, U: protocol<MyFunctionalUtils, _ArrayType> where U.Generator.Element == T> (arr1: U, _ arr2: U) -> Int? {
// OK, type U behaves as array type with elements T (=MyTypes)
var a = arr1
var b = arr2
a.append(T(2)) // add 2*7 to multsum
b.append(T(7))
return a.foo(Array(b))
/* Ok! */
}
let myInt2d = bar2(arr1d, arr2d) // 10, OK
let myInt2my = bar2(arr1my, arr2my) // 10, OK
extension T[]
bit lorsque vous cliquez sur le type de tableau dans XCode, mais ne voyez aucun moyen de l'implémenter sans obtenir d'erreur.