( Swift 2.x )
Você também pode estender a matriz para estar em conformidade com um protocolo contendo blue-rpints para métodos de tipo genérico, por exemplo, um protocolo contendo seus utilitários funcionais personalizados para todos os elementos genéricos da matriz em conformidade com alguma restrição de tipo, digamos protocolo MyTypes
. O bônus usando essa abordagem é que você pode escrever funções usando argumentos genéricos de matriz, com uma restrição de que esses argumentos de matriz devem estar em conformidade com o protocolo de utilitários de funções personalizadas, por exemplo, protocolo MyFunctionalUtils
.
Você pode obter esse comportamento implicitamente, digitando os elementos da matriz MyTypes
como ---, como mostrarei no método descrito abaixo ---, de maneira bem explícita, deixando seu cabeçalho genérico de funções da matriz mostrar diretamente as matrizes de entrada está em conformidade com MyFunctionalUtils
.
Começamos com Protocolos MyTypes
para uso como restrição de tipo; estenda os tipos que você deseja ajustar em seus genéricos por este protocolo (o exemplo abaixo estende os tipos fundamentais Int
e Double
também um 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
(mantendo blueprints de nossos utilitários genéricos adicionais de funções de matriz) e, posteriormente, a extensão de Matriz por MyFunctionalUtils
; implementação de métodos impressos em 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
}
}
Por fim, testes e dois exemplos mostrando uma função que recebe matrizes genéricas, com os seguintes casos, respectivamente
Mostrando afirmação implícita de que os parâmetros da matriz estão de acordo com o protocolo 'MyFunctionalUtils', via tipo restringindo os elementos das matrizes a 'MyTypes' (função bar1
).
Mostrando explicitamente que os parâmetros da matriz estão em conformidade com o protocolo 'MyFunctionalUtils' (função bar2
).
O teste e os exemplos a seguir:
/* 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 ao clicar em Command no tipo Array no XCode, mas não vendo nenhuma maneira de implementá-lo sem obter um erro.