Estou tentando descobrir algo com a nova linguagem Apple Swift. Digamos que eu costumava fazer algo como o seguinte no Objective-C. Eu tenho readonly
propriedades e elas não podem ser alteradas individualmente. No entanto, usando um método específico, as propriedades são alteradas de maneira lógica.
Tomo o exemplo a seguir, um relógio muito simples. Eu escreveria isso em 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 uma finalidade específica, não podemos tocar diretamente os segundos, minutos e horas, e só é permitido incrementar segundo a segundo usando um método. Somente esse método pode alterar os valores usando o truque das variáveis de instância.
Como não existem essas coisas no Swift, estou tentando encontrar um equivalente. Se eu fizer isso:
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++
}
}
}
}
Isso funcionaria, mas qualquer um poderia alterar diretamente as propriedades.
Talvez eu já tenha um design ruim no Objective-C e é por isso que o potencial novo equivalente do Swift não faz sentido. Se não e se alguém tiver uma resposta, ficaria muito grato;)
Talvez o futuro mecanismo de controle de acesso prometido pela Apple seja a resposta?
Obrigado!
fonte
Respostas:
Simplesmente prefixe a declaração de propriedade com
private(set)
:private
mantém local para um arquivo de origem, enquantointernal
local para o módulo / projeto.private(set)
cria umaread-only
propriedade, enquantoprivate
define ambosset
eget
como privado.fonte
Existem duas maneiras básicas de fazer o que você deseja. A primeira maneira é ter uma propriedade privada e uma propriedade pública computada que retorne essa propriedade:
Mas isso pode ser alcançado de uma maneira diferente e mais curta, conforme indicado na seção "Controle de acesso" do livro "A linguagem de programação Swift" :
Como uma observação lateral, você DEVE fornecer um inicializador público ao declarar um tipo público. Mesmo se você fornecer valores padrão para todas as propriedades,
init()
deverá ser definido explicitamente público:Isso também é explicado na mesma seção do livro, ao falar sobre inicializadores padrão.
fonte
Como não há controles de acesso (o que significa que você não pode fazer um contrato de acesso que seja diferente dependendo de quem é o chamador), eis o que eu faria por enquanto:
Isso apenas adiciona um nível de indireção, por assim dizer, ao acesso direto ao balcão; outra classe pode criar um relógio e acessar o contador diretamente. Mas a idéia - ou seja, o contrato que estamos tentando fazer - é que outra classe use apenas as propriedades e métodos de nível superior do Clock. Não podemos impor esse contrato, mas, na verdade, era praticamente impossível impor também no Objective-C.
fonte
Na verdade, o controle de acesso (que ainda não existe no Swift) não é tão imposto quanto você pode imaginar no Objetivo C. As pessoas podem modificar suas variáveis somente leitura diretamente, se realmente quiserem. Eles simplesmente não fazem isso com a interface pública da classe.
Você pode fazer algo semelhante no Swift (cortar e colar seu código, além de algumas modificações, eu não testei):
que é igual ao que você possui no objetivo C, exceto que as propriedades armazenadas reais são visíveis na interface pública.
No swift, você também pode fazer algo mais interessante, o que também no Objective C, mas provavelmente é mais bonito no swift (editado no navegador, eu não testei):
fonte