Estoy tratando de descubrir algo con el nuevo lenguaje Apple Swift. Digamos que solía hacer algo como lo siguiente en Objective-C. Tengo readonly
propiedades y no se pueden cambiar individualmente. Sin embargo, utilizando un método específico, las propiedades se cambian de forma lógica.
Tomo el siguiente ejemplo, un reloj muy simple. Escribiría esto en Objective-C.
@interface Clock : NSObject
@property (readonly) NSUInteger hours;
@property (readonly) NSUInteger minutes;
@property (readonly) NSUInteger seconds;
- (void)incrementSeconds;
@end
@implementation Clock
- (void)incrementSeconds {
_seconds++;
if (_seconds == 60) {
_seconds = 0;
_minutes++;
if (_minutes == 60) {
_minutes = 0;
_hours++;
}
}
}
@end
Para un propósito específico, no podemos tocar los segundos, minutos y horas directamente, y solo se permite incrementar segundo por segundo usando un método. Solo este método podría cambiar los valores utilizando el truco de las variables de instancia.
Como no hay tales cosas en Swift, estoy tratando de encontrar un equivalente. Si hago esto:
class Clock : NSObject {
var hours: UInt = 0
var minutes: UInt = 0
var seconds: UInt = 0
func incrementSeconds() {
self.seconds++
if self.seconds == 60 {
self.seconds = 0
self.minutes++
if self.minutes == 60 {
self.minutes = 0
self.hours++
}
}
}
}
Eso funcionaría, pero cualquiera podría cambiar directamente las propiedades.
Tal vez ya tenía un mal diseño en Objective-C y es por eso que el potencial nuevo equivalente de Swift no tiene sentido. Si no es así y si alguien tiene una respuesta, estaría muy agradecido;)
¿Quizás los futuros mecanismos de control de acceso prometidos por Apple son la respuesta?
¡Gracias!
fuente
Respuestas:
Simplemente prefija la declaración de propiedad con
private(set)
, así:private
lo mantiene local a un archivo fuente, mientras que lointernal
mantiene local al módulo / proyecto.private(set)
crea unaread-only
propiedad, mientrasprivate
establece ambos,set
yget
en privado.fuente
Hay dos formas básicas de hacer lo que quieres. La primera forma es tener una propiedad privada y una propiedad pública computada que devuelva esa propiedad:
Pero esto se puede lograr de una manera diferente y más corta, como se indica en la sección "Control de acceso" del libro "El lenguaje de programación Swift" :
Como nota al margen, DEBE proporcionar un inicializador público al declarar un tipo público. Incluso si proporciona valores predeterminados para todas las propiedades,
init()
debe definirse explícitamente como público:Esto también se explica en la misma sección del libro, cuando se habla de inicializadores predeterminados.
fuente
Dado que no hay controles de acceso (lo que significa que no puede hacer un contrato de acceso que difiera dependiendo de quién sea la persona que llama), esto es lo que haría por ahora:
Esto simplemente agrega un nivel de indirección, por así decirlo, al acceso directo al contador; otra clase puede hacer un reloj y luego acceder a su contador directamente. Pero la idea , es decir, el contrato que estamos tratando de hacer, es que otra clase solo use las propiedades y métodos de nivel superior del Reloj. No podemos hacer cumplir ese contrato, pero en realidad era prácticamente imposible hacerlo también en Objective-C.
fuente
En realidad, el control de acceso (que aún no existe en Swift) no se aplica tan bien como puede pensar en el Objetivo C. Las personas pueden modificar sus variables de solo lectura directamente, si realmente lo desean. Simplemente no lo hacen con la interfaz pública de la clase.
Puede hacer algo similar en Swift (cortar y pegar su código, más algunas modificaciones, no lo probé):
que es lo mismo que tiene en el Objetivo C, excepto que las propiedades reales almacenadas son visibles en la interfaz pública.
En swift también puedes hacer algo más interesante, que también puedes hacer en Objective C, pero probablemente sea más bonito en swift (editado en el navegador, no lo probé):
fuente