Propiedad interna de lectura y escritura rápida de solo lectura

103

En Swift, ¿cuál es la forma convencional de definir el patrón común en el que una propiedad debe ser externamente de solo lectura, pero modificable internamente por la clase (y subclases) que la poseen?

En Objective-C, existen las siguientes opciones:

  • Declare la propiedad como de solo lectura en la interfaz y use una extensión de clase para acceder a la propiedad internamente. Este es un acceso basado en mensajes, por lo que funciona bien con KVO, atomicity, etc.
  • Declare la propiedad como de solo lectura en la interfaz, pero acceda al ivar de respaldo internamente. Como el acceso predeterminado para un ivar está protegido, esto funciona bien en una jerarquía de clases, donde las subclases también podrán modificar el valor, pero el campo es de solo lectura.

En Java, la convención es:

  • Declare un campo protegido e implemente un getter (método) público de solo lectura.

¿Cuál es el modismo de Swift?

Jasper Blues
fuente

Respuestas:

219

Dada una propiedad de clase, puede especificar un nivel de acceso diferente prefijando la declaración de propiedad con el modificador de acceso seguido de geto setentre paréntesis. Por ejemplo, una propiedad de clase con un captador público y un definidor privado se declarará como:

private(set) public var readonlyProperty: Int

Lectura sugerida: Getters and Setters

Las consideraciones de Martin sobre el nivel de accesibilidad siguen siendo válidas, es decir, no hay protectedmodificador, internalrestringe el acceso solo al módulo, solo privateal archivo actual y publicsin restricciones.

Swift 3 notas

2 nuevos modificadores de acceso, fileprivatey opense han agregado al idioma, mientras que privatey publicse han modificado ligeramente:

  • opense aplica solo a la clase y a los miembros de la clase: se usa para permitir que una clase sea subclasificada o que un miembro sea anulado fuera del módulo donde están definidos. publicen cambio, hace que la clase o el miembro sean accesibles públicamente, pero no heredables ni anulables

  • privateahora hace que un miembro sea visible y accesible solo desde la declaración adjunta, mientras que fileprivatea todo el archivo donde está contenido

Más detalles aquí .

Antonio
fuente
¡Agradable! (Me tomo la libertad de agregar la varpalabra clave que falta para que se compile).
Martin R
oh muchas gracias :) Normalmente copio desde el patio de recreo y pego, pero esta vez probablemente lo he hecho mal.
Antonio
10
Tenga en cuenta que a partir de enero de 2015, esta sintaxis no es del todo correcta si la clase externa no lo es public; debería serlo internalo nada en absoluto (que por defecto es la clase que sea, publico internal), es decirprivate(set) var readonlyProperty: Int
Grimxn
1
Bueno, la sintaxis es correcta teniendo en cuenta que justo antes del código escribí una propiedad de clase con un captador público y un definidor privado ; es solo un ejemplo. Pero sí, los modificadores de acceso para propiedades deben ser "compatibles" con el modificador de acceso clase / estructura.
Antonio
Con respecto al último párrafo, supongo que esto ha cambiado desde que se escribió la respuesta, pero privateahora se restringe a la declaración actual (no al archivo) y fileprivateestá disponible para restringir al archivo actual. También publictiene algunas restricciones y openes necesario para no tener restricciones. Detalles aquí .
Nigel B. Peck
2

Según @Antonio, podemos usar una sola propiedad para acceder como readOnlyvalor de la propiedad de forma pública y readWriteprivada. A continuación se muestra mi ilustración:

class MyClass {

    private(set) public var publicReadOnly: Int = 10

    //as below, we can modify the value within same class which is private access
    func increment() {
        publicReadOnly += 1
    }

    func decrement() {
        publicReadOnly -= 1
    }
}

let object = MyClass()
print("Initial  valule: \(object.publicReadOnly)")

//For below line we get the compile error saying : "Left side of mutating operator isn't mutable: 'publicReadOnly' setter is inaccessible"
//object.publicReadOnly += 1

object.increment()
print("After increment method call: \(object.publicReadOnly)")

object.decrement()
print("After decrement method call: \(object.publicReadOnly)")

Y aquí está la salida:

  Initial  valule: 10
  After increment method call: 11
  After decrement method call: 10
Santosh
fuente