( Swift 2.x )
È inoltre possibile estendere l'array per conformarsi a un protocollo contenente blueprint per metodi di tipo generico, ad esempio un protocollo contenente i programmi di utilità personalizzati per tutti gli elementi dell'array generico conformi a un vincolo di tipo, ad esempio protocollo MyTypes
. Il vantaggio di questo approccio è che puoi scrivere funzioni prendendo argomenti di array generici, con un vincolo che questi argomenti di array devono essere conformi al tuo protocollo di utilità di funzione personalizzata, ad esempio protocollo MyFunctionalUtils
.
È possibile ottenere questo comportamento in modo implicito, limitando gli elementi dell'array a MyTypes
, o --- come mostrerò nel metodo che descrivo di seguito ---, abbastanza ordinatamente, esplicitamente, lasciando che l'intestazione delle funzioni dell'array generico mostri direttamente che gli array di input conforme a MyFunctionalUtils
.
Iniziamo con i protocolli MyTypes
da utilizzare come vincolo di tipo; estendi i tipi che vuoi adattare ai tuoi generici con questo protocollo (l'esempio che segue estende i tipi fondamentali Int
e Double
anche un tipo personalizzato 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)
}
Protocollo MyFunctionalUtils
(che contiene i progetti delle nostre utilità aggiuntive per le funzioni di array generici) e, successivamente, l'estensione di Array di MyFunctionalUtils
; implementazione di metodi stampati in blu:
/* 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
}
}
Infine, test e due esempi che mostrano una funzione che prende array generici, con i seguenti casi, rispettivamente
Mostrando un'asserzione implicita che i parametri dell'array sono conformi al protocollo "MyFunctionalUtils", tramite il tipo che vincola gli elementi degli array a "MyTypes" (funzione bar1
).
Mostrando esplicitamente che i parametri dell'array sono conformi al protocollo 'MyFunctionalUtils' (funzione bar2
).
Il test e gli esempi seguono:
/* 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 quando si fa clic tenendo premuto il tasto Comando sul tipo di array in XCode, ma non si vede alcun modo per implementarlo senza ottenere un errore.