Explorando tipos opacos en iOS Swift

Jan 24 2023
Como desarrolladores de iOS, buscamos constantemente formas de escribir código limpio, fácil de mantener y reutilizable. Una característica del sistema de tipos de Swift que puede ayudarnos a lograr esto son los tipos opacos.
Foto de Raul Perțe en Unsplash

Como desarrolladores de iOS, buscamos constantemente formas de escribir código limpio, fácil de mantener y reutilizable. Una característica del sistema de tipos de Swift que puede ayudarnos a lograr esto son los tipos opacos . En este artículo, exploraremos qué son los tipos opacos , cómo se pueden usar y sus beneficios. También veremos cómo se pueden usar los tipos opacos y cómo podemos crear un borrado de tipos usándolo.

¿Qué son los tipos opacos?

Los tipos opacos son una característica del sistema de tipos de Swift que permite que una función o método devuelva un tipo específico sin especificar exactamente cuál es ese tipo. Esto permite una mayor flexibilidad y abstracción en el código.

Uno de los casos de uso más comunes para los tipos opacos es cuando se define un tipo de retorno para una función o método. En el pasado, los desarrolladores tenían que especificar el tipo exacto que se devolvía, lo que podía provocar un acoplamiento estrecho y una menor flexibilidad en el código. Con los tipos opacos, podemos especificar un tipo de devolución como algún Protocolo o some Class, indicando al compilador que el tipo devuelto se ajusta a un determinado protocolo o hereda de una determinada clase, sin especificar el tipo exacto.

echemos un vistazo al siguiente ejemplo. Definiremos un protocolo llamado Enginecon un tipo asociado Codey una propiedad engineCodede tipo Code. El protocolo también define un método description()que devuelve una representación de cadena del motor.

protocol Engine {
  associatedtype Code
  var engineCode: Code { get }
  func description() -> String
}

struct Toyota: Engine {
  typealias Code = String
  var engineCode: Code
  func description() -> String {
    "Toyota"
  }
}
struct Mercedes: Engine {
  typealias Code = Int
  var engineCode: Code
  func description() -> String {
    "Mercedes Benz"
  }
}

struct CarManufacturer {
  func createCarModel() -> some Engine {
    Mercedes(engineCode: 219440)
  }
}

enum EngineType {
  case internalCombustion
  case hybridEngine
}

struct CarManufacturer {
  func createCarModel(type: EngineType) -> some Engine {
    switch type {
    case .hybridEngine: return Mercedes(engineCode: 219440)
    case .internalCombustion: return Toyota(engineCode: "67672674")
    }
  }
}

¿Qué es el borrado de tipos?

El borrado de tipos en el desarrollo de iOS con Swift es una técnica utilizada para ocultar el tipo específico de una clase o protocolo genérico. Permite que una clase o protocolo genérico se ajuste a un protocolo o clase no genérico, al mismo tiempo que conserva la funcionalidad del tipo genérico.

Por ejemplo, consideremos el siguiente protocolo genérico:

protocol Container {
    associatedtype T
    var items: [T] { get }
    mutating func add(_ item: T)
}

struct AnyContainer<T>: Container {
    private var _items: [T]
    var items: [T] {
        return _items
    }
    mutating func add(_ item: T) {
        _items.append(item)
    }
    
    init<C: Container>(_ container: C) where C.T == T {
        _items = container.items
    }
}

Resolveremos nuestro problema anterior con la devolución de Engineun objeto mediante la creación de una AnyEngineestructura que borre el tipo de motor específico y, en su lugar, devuelva AnyEngine.

struct AnyEngine: Engine {
  private let _description: () -> String
  private let _engineCode: Any
  
  init<E: Engine>(_ engine: E) {
    _description = engine.description
    _engineCode = engine.engineCode
  }
  
  var engineCode: Any {
    return _engineCode
  }
  func description() -> String {
    return _description()
  }
}

struct CarManufacturer {
    func createCarModel(type: EngineType) -> some Engine {
        switch type {
        case .hybridEngine: return AnyEngine(Mercedes(engineCode: 219440))
        case .internalCombustion: return AnyEngine(Toyota(engineCode: "67672674"))
        }
    }
}

let carManufacturer = CarManufacturer()
print(carManufacturer.createCarModel(type: .hybridEngine).description())

De esta forma, podemos usar la técnica de borrado de tipos para ocultar los detalles de implementación de un tipo específico y devolver cualquier tipo de motor sin especificar el tipo exacto. Esto permite una mayor libertad para cambiar la implementación de la CarManufacturerestructura sin afectar a las personas que llaman a la estructura.

Beneficios de los tipos opacos

  • Mayor flexibilidad : los tipos opacos permiten una mayor flexibilidad en el código, ya que permiten que una función o método devuelva un tipo específico sin especificar exactamente cuál es ese tipo. Esto permite una mayor libertad para cambiar la implementación sin afectar a las personas que llaman del tipo.
  • Mayor abstracción : los tipos opacos permiten una mayor abstracción en el código, ya que ocultan los detalles de implementación de un tipo específico. Esto permite una mayor libertad para cambiar la implementación sin afectar a las personas que llaman del tipo.

func arrayElements<T: Numeric>(array: Array<T>) -> LazyMapSequence<Array<T>,T> {
  return array.lazy.map { $0 * $0}
}

Con tipos opacos, podemos hacer que la función sea más expresiva y flexible especificando el tipo de retorno como some Sequence.

func arrayElements<T: Numeric>(array: Array<T>) -> some Sequence {
  return array.lazy.map { $0 * $0}
}

Además de los beneficios descritos anteriormente, los tipos opacos también juegan un papel crucial en el mundo de SwiftUI. En SwiftUI, los tipos opacos se utilizan ampliamente para proporcionar una API simplificada para las vistas.

Por ejemplo, considere la siguiente ContentViewestructura que se ajusta al Viewprotocolo. Se requiere la bodypropiedad del protocolo para devolver un valor de tipo .Viewsome View

import SwiftUI

struct ContentView: View {  
    var body: some View {
       Text("Hello Wold")
    }
}

Además, SwiftUI también proporciona el PreviewProviderprotocolo que permite a los desarrolladores obtener una vista previa de sus vistas en Xcode. También se requiere que la previewspropiedad del PreviewProviderprotocolo devuelva un valor de tipo some View.

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

En resumen, los tipos opacos son una característica poderosa del sistema de tipos de Swift que permite una mayor flexibilidad y abstracción en el código. Permiten que una función o método devuelva un tipo específico sin especificar exactamente qué tipo es, lo que hace que el código sea más reutilizable y mantenible. Además de esto, los tipos opacos también juegan un papel crucial en el mundo de SwiftUIuna API simplificada para vistas. Como desarrolladores de iOS, es importante comprender el concepto y el uso opaque typespara escribir código limpio, fácil de mantener y reutilizable.

¡Gracias por leer este artículo!

Si tiene alguna consulta relacionada con este tema, puede comunicarse conmigo en [email protected] y @Somendra_Dev