Пытаюсь что-то придумать с новым языком Apple Swift. Допустим, я делал что-то вроде следующего в Objective-C. У меня есть readonly
свойства, и их нельзя изменить индивидуально. Однако при использовании определенного метода свойства изменяются логическим образом.
Я беру следующий пример, очень простые часы. Я бы написал это в 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
Для конкретной цели мы не можем напрямую касаться секунд, минут и часов, и с помощью метода можно увеличивать только секунду на секунду. Только этот метод может изменять значения, используя уловку переменных экземпляра.
Поскольку в Swift таких вещей нет, пытаюсь найти аналог. Если я сделаю это:
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++
}
}
}
}
Это сработает, но любой может изменить свойства напрямую.
Возможно, у меня уже был плохой дизайн в Objective-C, и поэтому потенциальный новый эквивалент Swift не имеет смысла. Если нет и если у кого-то есть ответ, буду очень признателен;)
Может быть, обещанные Apple будущие механизмы контроля доступа станут ответом?
Спасибо!
источник
Ответы:
Просто добавьте к объявлению свойства префикс
private(set)
, например:private
сохраняет его локальным по отношению к исходному файлу, ноinternal
сохраняет его локальным по отношению к модулю / проекту.private(set)
создаетread-only
свойство, аprivate
устанавливает как частное , такset
иget
частное.источник
Есть два основных способа делать то, что вы хотите. Первый способ - иметь частное свойство и общедоступное вычисляемое свойство, которое возвращает это свойство:
Но этого можно добиться другим, более коротким способом, как указано в разделе «Контроль доступа» книги «Язык программирования Swift» :
В качестве примечания, вы ДОЛЖНЫ предоставить публичный инициализатор при объявлении публичного типа. Даже если вы предоставляете значения по умолчанию для всех свойств, они
init()
должны быть явно определены как public:Это также объясняется в том же разделе книги, когда речь идет об инициализаторах по умолчанию.
источник
Поскольку нет элементов управления доступом (это означает, что вы не можете заключить контракт доступа, который отличается в зависимости от того, кто звонит), вот что я бы сейчас сделал:
Это просто добавляет уровень косвенности, так сказать, к прямому доступу к счетчику; другой класс может создать Clock, а затем напрямую обращаться к его счетчику. Но идея - то есть контракт, который мы пытаемся заключить - состоит в том, что другой класс должен использовать только свойства и методы верхнего уровня Clock. Мы не можем обеспечить соблюдение этого контракта, но на самом деле это было практически невозможно и в Objective-C.
источник
На самом деле контроль доступа (который еще не существует в Swift) не так строг, как вы думаете в Objective C. Люди могут напрямую изменять ваши переменные только для чтения, если они действительно этого хотят. Они просто не делают этого с открытым интерфейсом класса.
Вы можете сделать что-то подобное в Swift (вырезать и вставить свой код, плюс некоторые модификации, я не тестировал):
это то же самое, что и в Objective C, за исключением того, что фактические сохраненные свойства видны в общедоступном интерфейсе.
В Swift вы также можете сделать что-то более интересное, что вы также можете сделать в Objective C, но, вероятно, это будет красивее в Swift (отредактировано в браузере, я не тестировал):
источник