ios swift protocol-oriented

ios - Swift-Extensiones de protocolo-Valores predeterminados de la propiedad



protocol-oriented (3)

Es por eso que no fue posible establecer las propiedades.

La propiedad se convierte en una propiedad calculada, lo que significa que no tiene una variable de respaldo como _x como lo haría en ObjC. En el código de la solución a continuación, puede ver que xTimesTwo no almacena nada, sino que simplemente calcula el resultado de x.

Ver Documentos oficiales en propiedades calculadas.

La funcionalidad que desea también puede ser Property Observers.

Setters / getters son diferentes de lo que eran en Objective-C.

Lo que necesitas es:

var x:Int var xTimesTwo:Int { set { x = newValue / 2 } get { return x * 2 } }

Puedes modificar otras propiedades dentro del setter / getters, que es para lo que están destinadas

Digamos que tengo el siguiente protocolo:

protocol Identifiable { var id: Int {get} var name: String {get} }

Y que tengo las siguientes estructuras:

struct A: Identifiable { var id: Int var name: String } struct B: Identifiable { var id: Int var name: String }

Como puede ver, tuve que ''conformarme'' con el protocolo identificable en la estructura A y la estructura B. Pero imagine que si tuviera N más estructuras que deben ajustarse a este protocolo ... no quiero ''copiar / pegar'' ''la conformidad (var id: Int, var nombre: String)

Entonces creo una extensión de protocolo :

extension Identifiable { var id: Int { return 0 } var name: String { return "default" } }

Con esta extensión ahora puedo crear una estructura que se ajuste al protocolo Identificable sin tener que implementar ambas propiedades:

struct C: Identifiable { }

Ahora el problema es que no puedo establecer un valor para la propiedad id o la propiedad name:

var c: C = C() c.id = 12 // Cannot assign to property: ''id'' is a get-only property

Esto sucede porque en el protocolo identificable, id y name solo son gettable. Ahora si cambio las propiedades de identificación y nombre a {get set} , aparece el siguiente error:

El tipo ''C'' no se ajusta al protocolo ''Identificable''

Este error ocurre porque no he implementado un setter en la extensión de protocolo ... Así que cambio la extensión del protocolo:

extension Identifiable { var id: Int { get { return 0 } set { } } var name: String { get { return "default" } set { } } }

Ahora el error desaparece pero si establezco un nuevo valor para el id o name, obtiene el valor predeterminado (getter). Por supuesto, el colocador está vacío .

Mi pregunta es: ¿Qué parte del código tengo que poner dentro del setter? Porque si agrego self.id = newValue se bloquea (recursivo).

Gracias por adelantado.


Los protocolos y las extensiones de protocolo son muy potentes, pero tienden a ser más útiles para las funciones y propiedades de solo lectura.

para lo que estás tratando de lograr (propiedades almacenadas con un valor predeterminado), las clases y la herencia en realidad podrían ser la solución más elegante

algo como:

class Identifiable { var id: Int = 0 var name: String = "default" } class A:Identifiable { } class B:Identifiable { } let a = A() print("/(a.id) /(a.name)") a.id = 42 a.name = "foo" print("/(a.id) /(a.name)")


Parece que desea agregar una stored property a un tipo a través de la extensión de protocolo. Sin embargo, esto no es posible porque con las extensiones no puede agregar una propiedad almacenada.

Puedo mostrarte un par de alternativas.

Subclasificación (programación orientada a objetos)

La forma más fácil (como probablemente ya lo imagine) es usar clases en lugar de estructuras.

class IdentifiableBase { var id = 0 var name = "default" } class A: IdentifiableBase { } let a = A() a.name = "test" print(a.name) // test

Contras: en este caso, su clase A debe heredar de IdentifiableBase y como en Swift no hay herencia múltiple, esta será la única clase A de la que podrá heredar.

Componentes (Programación Orientada a Protocolo)

Esta técnica es bastante popular en el desarrollo de juegos

struct IdentifiableComponent { var id = 0 var name = "default" } protocol HasIdentifiableComponent { var identifiableComponent: IdentifiableComponent { get set } } protocol Identifiable: HasIdentifiableComponent { } extension Identifiable { var id: Int { get { return identifiableComponent.id } set { identifiableComponent.id = newValue } } var name: String { get { return identifiableComponent.name } set { identifiableComponent.name = newValue } } }

Ahora puede hacer que su tipo se ajuste a Identifiable simplemente escribiendo

struct A: Identifiable { var identifiableComponent = IdentifiableComponent() }

Prueba

var a = A() a.name = "test" print(a.name) // test