Estoy tratando de hacer funcionar una extensión Swift con dos tipos genéricos. Traté de hacer un ejemplo.
Tenemos una caja donde podemos para diferentes tipos.
class Box<E> { var value: E init(val: E) { value = val } }Ahora tenemos un Itemtype especial que nuevamente puede tener diferentes tipos
class Item<Type> { var value: Type init(val: Type) { value = val } } Ahora podemos crear fácilmente un Box<Item<Int>> . Pero tal vez queramos cambiarlo a Box<Item<String>> Así que me gustaría tener una extensión para cambiar de Box<Item<A>> a Box<Item<B>>
lo que si funciona es lo siguiente
extension Box where E: Item<Any> { func mapOnItem(function: (Any) -> Any) -> Box<Item<Any>> { return Box<Item<Any>>(val: Item(val: function(value.value))) } }Pero esto no es muy útil porque no tenemos la conexión entre el valor de retorno de la función y el valor de retorno de mapOnItem.
Así que traté de arreglar pero estoy fallando. Mi entendimiento sería introducir otra variable genérica aquí.
extension Box<A> where E: Item<A> { func mapOnItem<B>(function: (A) -> B) -> Box<Item<B>> { return Box<Item<B>>(val: Item(val: function(value.value))) } }me sale el error
La extensión restringida debe declararse en el tipo genérico no especializado 'Box' con restricciones especificadas por una cláusula 'where'
¿Tienes alguna pista para mí? ¿Es posible?
Gracias por tu ayuda
Martín
Una restricción en la extensión puede restringir el marcador de posición tipo E a tipos o protocolos concretos, por ejemplo:
extension Box where E: Item<Any> {} extension Box where E == String {} extension Box where E: Numeric {}Pero no puede poner una restricción genérica en la extensión:
extension Box<A> where E: Item<A> {} // Error: Constrained extension must be declared on the unspecialized generic // type 'Box' with constraints specified by a 'where' clauseLa solución es restringir el método en su lugar:
extension Box { func mapOnItem<A, B>(function: (A) -> B) -> Box<Item<B>> where E: Item<A> { return Box<Item<B>>(val: Item(val: function(self.value.value))) } }