Extensiones y Genericos
## Objetivos de Aprendizaje
- Extender tipos existentes con extensiones
- Usar delegacion de protocolos
- Dominar conceptos basicos de genericos
- Escribir funciones y tipos genericos
## Extensiones
### Agregar Funcionalidad
```swift
extension Int {
func alCuadrado() -> Int {
return self * self
}
}
let numero = 5
print(numero.alCuadrado()) // 25
```
### Agregar Propiedades Calculadas
```swift
extension Double {
var kmAMillas: Double {
return self * 0.621371
}
var millasAKm: Double {
return self * 1.60934
}
}
let distancia = 10.0
print("\(distancia) km = \(distancia.kmAMillas) millas")
```
### Agregar Inicializadores
```swift
struct Punto {
var x: Int
var y: Int
}
extension Punto {
init(xy: Int) {
self.init(x: xy, y: xy)
}
}
let origen = Punto(xy: 0) // Punto(x: 0, y: 0)
```
### Agregar Metodos
```swift
extension Array {
func promedio() -> Double? {
guard !isEmpty else { return nil }
return Double(reduce(0, +)) / Double(count)
}
}
let puntuaciones = [90, 85, 92, 88]
print(puntuaciones.promedio()) // Optional(88.75)
```
## Conformidad a Protocolos
### Extender para Conformar
```swift
protocol Imprimible {
func descripcion() -> String
}
extension Int: Imprimible {
func descripcion() -> String {
return "Numero: \(self)"
}
}
print(42.descripcion()) // "Numero: 42"
```
### Agregar Requisitos de Protocolo
```swift
extension Array where Element: Equatable {
func contiene(_ elemento: Element) -> Bool {
for item in self {
if item == elemento {
return true
}
}
return false
}
}
let nums = [1, 2, 3, 4, 5]
print(nums.contiene(3)) // true
print(nums.contiene(10)) // false
```
## Delegacion de Protocolos
### Definir Protocolos
```swift
protocol ManejadorDatosDelegate: AnyObject {
func datosRecibidos(_ datos: Data)
func falloConError(_ error: Error)
}
class ManejadorDatos {
weak var delegate: ManejadorDatosDelegate?
func obtenerDatos() {
// ... obtener datos
let datos = Data()
delegate?.datosRecibidos(datos)
}
}
```
### Implementar Delegate
```swift
class ControladorVista: ManejadorDatosDelegate {
let manejador = ManejadorDatos()
init() {
manejador.delegate = self
}
func datosRecibidos(_ datos: Data) {
print("Recibidos \(datos.count) bytes")
}
func falloConError(_ error: Error) {
print("Error: \(error)")
}
}
```
### Beneficios del Patron Delegate
- Acoplamiento flexible
- Flexibilidad
- Multiples delegates posibles
- Separacion clara de responsabilidades
## Genericos
### Por Que Genericos?
```swift
// Sin genericos - codigo repetido
func intercambiarEnteros(_ a: inout Int, _ b: inout Int) {
let temp = a
a = b
b = temp
}
func intercambiarCadenas(_ a: inout String, _ b: inout String) {
let temp = a
a = b
b = temp
}
// Con genericos - una funcion
func intercambiar(_ a: inout T, _ b: inout T) {
let temp = a
a = b
b = temp
}
var x = 1, y = 2
intercambiar(&x, &y)
var s1 = "Hola", s2 = "Mundo"
intercambiar(&s1, &s2)
```
## Funciones Genericas
### Sintaxis
```swift
func identidad(_ valor: T) -> T {
return valor
}
let num = identidad(42) // Inferido como Int
let str = identidad("hola") // Inferido como String
```
### Multiples Parametros de Tipo
```swift
func combinar(_ a: A, _ b: B) -> (A, B) {
return (a, b)
}
combinar(1, "uno") // (1, "uno")
```
### Restricciones de Tipo
```swift
// Restriccion Comparable
func maximo(_ a: T, _ b: T) -> T {
return a > b ? a : b
}
maximo(5, 10) // 10
maximo("manzana", "banana") // "banana"
```
## Tipos Genericos
### Struct Generico
```swift
struct Pila {
var elementos: [Elemento] = []
mutating func apilar(_ item: Elemento) {
elementos.append(item)
}
mutating func desapilar() -> Elemento? {
return elementos.popLast()
}
func ver() -> Elemento? {
return elementos.last
}
}
var pilaInt = Pila()
pilaInt.apilar(1)
pilaInt.apilar(2)
print(pilaInt.desapilar()) // Optional(2)
var pilaCadena = Pila()
pilaCadena.apilar("Hola")
pilaCadena.apilar("Mundo")
```
### Clase Generica
```swift
class Cola {
private var elementos: [Elemento] = []
func encolar(_ item: Elemento) {
elementos.append(item)
}
func desencolar() -> Elemento? {
return elementos.removeFirst()
}
func ver() -> Elemento? {
return elementos.first
}
}
```
### Enum Generico
```swift
enum Resultado {
case exito(Valor)
case fracaso(Error)
}
let exito: Resultado = .exito(42)
let fracaso: Resultado = .fracaso("Ocurrio un error")
```
## Restricciones de Tipo en Extensiones
### Sintaxis de Restricciones de Tipo
```swift
func encontrarIndice(de valor: T, en arreglo: [T]) -> Int? {
for (indice, item) in arreglo.enumerated() {
if item == valor {
return indice
}
}
return nil
}
```
### Multiples Restricciones
```swift
func encontrarCadena(en coleccion: T) -> T.Element?
where T.Element == String {
return coleccion.first(where: { !$0.isEmpty })
}
```
### Restricciones de Protocolo
```swift
func procesar(valores: [T]) -> T? {
return valores.filter { $0 > 0 }.max()
}
procesar(valores: [1, -2, 3, 0]) // Optional(3)
```
## Extensiones con Genericos
### Extender Tipos Genericos
```swift
extension Pila where Elemento: Comparable {
func ordenado() -> [Elemento] {
return elementos.ordenado()
}
}
var pila = Pila()
pila.apilar(3)
pila.apilar(1)
pila.apilar(2)
print(pila.ordenado()) // [1, 2, 3]
```
### Extension con Self
```swift
extension Numeric {
func alCuadrado() -> Self {
return self * self
}
}
let num: Int = 5
print(num.alCuadrado()) // 25
let dbl: Double = 3.0
print(dbl.alCuadrado()) // 9.0
```
## Tipos Asociados
### Protocolo con Tipo Asociado
```swift
protocol Contenedor {
associatedtype Elemento
mutating func append(_ item: Elemento)
var cantidad: Int { get }
subscript(i: Int) -> Elemento { get }
}
```
### Struct Generico Conformando
```swift
struct ContenedorInt: Contenedor {
private var elementos: [Int] = []
mutating func append(_ item: Int) {
elementos.append(item)
}
var cantidad: Int { elementos.cantidad }
subscript(i: Int) -> Int {
return elementos[i]
}
}
```
## Tipos Opacos
### Palabra Clave some
```swift
protocol Figura {
func dibujar()
}
struct Circulo: Figura {
func dibujar() { print("Circulo") }
}
struct Cuadrado: Figura {
func dibujar() { print("Cuadrado") }
}
func hacerFigura() -> some Figura {
return Circulo()
}
let figura = hacerFigura()
figura.dibujar() // Circulo
```
### Casos de Uso
```swift
// SwiftUI usa tipos de retorno opacos
func hacerVistaContenido() -> some Vista {
Texto("Hola")
}
```
## Resumen
- Las extensiones agregan funcionalidad a tipos existentes
- Propiedades calculadas, metodos, inicializadores pueden ser agregados
- Usar clausula `where` para conformidad condicional
- La delegacion separa preocupaciones via protocolos
- Los genericos permiten codigo reutilizable seguro para tipos
- Restricciones de tipo: ``
- Funciones genericas: `func identidad(_ x: T) -> T`
- Tipos genericos: `struct Pila`
- Tipos asociados para protocolos genericos
- `some` para tipos de retorno opacos
Comments
Comments powered by Giscus
To enable comments, add your Giscus embed code here.
Learn more about Giscus →