( Swift 2.x )
También puede extender la matriz para que se ajuste a un protocolo que contenga blue-rpints para métodos de tipo genérico, por ejemplo, un protocolo que contenga sus utilidades funcionales personalizadas para todos los elementos de matriz genéricos que se ajusten a alguna restricción de tipo, por ejemplo, protocolo MyTypes
. La ventaja de usar este enfoque es que puede escribir funciones tomando argumentos de matriz genéricos, con la restricción de que estos argumentos de matriz deben ajustarse a su protocolo de utilidades de funciones personalizadas, digamos protocolo MyFunctionalUtils
.
Puede obtener este comportamiento implícitamente, al restringir los elementos de la matriz a MyTypes
, o --- como mostraré en el método que describo a continuación ---, de manera bastante clara y explícita, dejando que el encabezado genérico de las funciones de la matriz muestre directamente las matrices de entrada se ajusta a MyFunctionalUtils
.
Comenzamos con Protocolos MyTypes
para usar como restricción de tipo; amplíe los tipos que desea incluir en sus genéricos mediante este protocolo (el ejemplo a continuación amplía los tipos fundamentales Int
y Double
también un tipo personalizado 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)
}
Protocolo MyFunctionalUtils
(que contiene planos de nuestras utilidades de funciones de matriz genéricas adicionales) y, posteriormente, la extensión de Array por MyFunctionalUtils
; implementación de métodos impresos en azul:
/* 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
}
}
Finalmente, pruebas y dos ejemplos que muestran una función que toma matrices genéricas, con los siguientes casos, respectivamente
Mostrando una afirmación implícita de que los parámetros de la matriz se ajustan al protocolo 'MyFunctionalUtils', a través del tipo que restringe los elementos de la matriz a 'MyTypes' (función bar1
).
Mostrando explícitamente que los parámetros de la matriz se ajustan al protocolo 'MyFunctionalUtils' (función bar2
).
La prueba y los ejemplos siguientes:
/* 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 cuando Comando-clic en el tipo Array en XCode, pero no ve ninguna forma de implementarlo sin obtener un error.