La function genérica Swift llama a otra function genérica

Estoy usando Swift 2.2 en XCode 7.3.1 e intentando llamar a una function Generic desde otra function Generic .

Código

 class Thing1 { let variable: SomeProtocol init<A: SomeProtocol>(variable: A) { self.variable = variable self.add1(self.variable) } func add1<A: SomeProtocol>(stuff: A) { let thing: Thing2 = Thing2() thing.add2(stuff) } } class Thing2 { func add2<A: SomeProtocol>(stuff: A) { } } protocol SomeProtocol { } add1("a") // Cannot invoke 'add1' with an argument list of type '(String)' add1(4) // Cannot invoke 'add1' with an argument list of type '(Int)' 

Me sale el error

 'Cannot invoke add with an argument of list type '(Whatever type I used to call the function)'' 

El problema es que los types abstractos en Swift no necesariamente se ajustan a sí mismos , por lo tanto, no se puede usar un tipo SomeProtocol como una cosa SomeProtocol concreta que se ajuste a SomeProtocol (que es lo que su function genérica add1 espera como argumento).

La solución más simple en su caso, por lo tanto, es simplemente usar el argumento de la variable genérica, en lugar de la propiedad de la variable , ya que es un genérico, se escribe como algo concreto que se ajusta a SomeProtocol , que puede pasarse a su function add1 :

 init<A: SomeProtocol>(variable: A) { self.variable = variable add1(variable) } 

Sin embargo, para evitar este tipo de problemas más adelante, es posible que desee considerar hacer su class genérica, suponiendo que su propiedad variable debe ser de tipo constante a lo largo de la vida de una instancia determinada de Thing1 :

 class Thing1<A:SomeProtocol> { let variable: A init(variable: A) { self.variable = variable add1(variable) } func add1(stuff: A) { let thing = Thing2() thing.add2(stuff) } } 

O bien, puede refactorizar su código para usar el tipo abstracto SomeProtocol , que le permitirá trabajar con cualquier tipo que se ajuste a SomeProtocol (por ejemplo, le permite mezclar diferentes instancias Thing1 con diferentes types de variable en una matriz):

 class Thing1 { let variable: SomeProtocol init(variable: SomeProtocol) { self.variable = variable add1(variable) } func add1(stuff: SomeProtocol) { let thing = Thing2() thing.add2(stuff) } } class Thing2 { func add2(stuff: SomeProtocol) { } } 

Aunque siempre debe tener en count los costos adicionales que conlleva el uso de types abstractos, consulte esta gran charla de WWDC para get más información .

Agregar las extensiones a String e Int y build objects Thing1 hace que funcione:

 extension String: SomeProtocol{} extension Int: SomeProtocol{} Thing1(variable: "a").add1("a") Thing1(variable: 2).add1(4)