Saltar al contenido

Programación orientada a un protocolo rápido

Extensiones del Protocolo

Los protocolos sirven como planos: nos dicen lo que los adoptantes deben implementar, pero no se puede proporcionar la implementación dentro de un protocolo. ¿Y si necesitamos definir el comportamiento por defecto para los tipos conformes? Necesitamos implementarlo en una clase base, ¿correcto? ¡Incorrecto! Tener que depender de una clase base para la implementación por defecto eclipsaría los beneficios de los protocolos. Además, eso no funcionaría para los tipos de valores. Por suerte, hay otra forma: ¡las extensiones de protocolo son la solución! En Swift, puedes extender un protocolo y proporcionar una implementación por defecto para los métodos, las propiedades calculadas, los subíndices y los inicializadores de conveniencia. En el siguiente ejemplo, proporcioné una implementación por defecto para el tipo método uid().

12345extensionEntity{estaticfuncuid()- >String{returnUUID().uuidString }}

swift

Programación orientada a un protocolo rápido
Programación orientada a un protocolo rápido

Ahora los tipos que adoptan el protocolo ya no necesitan implementar el método uid().

1234567structOrder:Entity{var nombre:Stringlet uid_String=Order.uid()}let order =Order(name: "My Order")print(order.uid)// 4812B485-3965-443B-A76D-72986B0A4FF4

swift

Protocolo de herencia

Un protocolo puede heredar de otros protocolos y luego agregar más requisitos además de los que hereda. En el siguiente ejemplo, el protocolo Persistable hereda del protocolo Entidad que introduje anteriormente. Añade el requisito de guardar una entidad para archivarla y cargarla basándose en su identificador único.

1234protocoloPersistable:Entidad{funcwrite(instance:Entidad, a filePath:String)init?(por uid:String)}

swift

Los tipos que adopten el protocolo Persistable deben satisfacer los requisitos definidos tanto en el protocolo de la Entidad como en el Persistable.

Si su tipo requiere capacidades de persistencia, debería implementar el protocolo Persistable.

12345678structPersistableEntity:Persistable{var name:Stringfuncwrite(instance:Entity, to filePath:String){// ...}init?(by uid:String){/// trata de cargar desde el sistema de archivos basado en id}}

swift

Mientras que los tipos que no necesitan ser perseguidos sólo aplicarán el protocolo de la Entidad:

123structInMemoryEntity:Entity{var nombre:String}

swift

La herencia del protocolo es una característica poderosa que permite diseños más granulares y flexibles.

Composición del Protocolo

Swift no permite la herencia múltiple para las clases. Sin embargo, los tipos Swift pueden adoptar múltiples protocolos. A veces, esta característica puede resultar útil.

Aquí hay un ejemplo: asumamos que necesitamos un tipo que represente a una Entidad.

También tenemos que comparar los casos de un tipo determinado. Y queremos proporcionar una descripción personalizada, también.

Tenemos tres protocolos que definen los requisitos mencionados:

  • Entidad
  • Ecuatable
  • CustomStringConvertible

Si estas fueran clases base, tendríamos que fusionar la funcionalidad en una superclase; sin embargo, con la composición de POP y el protocolo, la solución se convierte:

123456789101112131415structMyEntity:Entity,Equatable,CustomStringConvertible{var name:String// Equatablepublicstaticfunc==(lhs:MyEntity, rhs:MyEntity)-{Bool{return lhs.name == rhs.name }// CustomStringConvertiblepublicvar description:String{return "MyEntity: (nombre)"}}dejar que la entidad1 =MyEntity(nombre: "42")imprimir(entidad1)dejar que la entidad2 =MyEntity(nombre: "42")afirmar(entidad1 == entidad2, "Las entidades serán iguales")

swift

Este diseño no sólo es más flexible que exprimir toda la funcionalidad requerida en una clase base monolítica, sino que también funciona para los tipos de valor.