Внешнее свойство Swift только для чтения, внутреннее свойство для чтения и записи

103

В Swift - это обычный способ определения общего шаблона, в котором свойство должно быть доступно только для чтения извне, но может изменяться внутри класса (и подклассов), которому оно принадлежит.

В Objective-C есть следующие параметры:

  • Объявите свойство как доступное только для чтения в интерфейсе и используйте расширение класса для внутреннего доступа к свойству. Это доступ на основе сообщений, поэтому он отлично работает с KVO, атомарностью и т. Д.
  • Объявите свойство как доступное только для чтения в интерфейсе, но получите доступ к резервному ivar внутри. Поскольку доступ по умолчанию для ivar защищен, это хорошо работает в иерархии классов, где подклассы также могут изменять значение, но в противном случае поле доступно только для чтения.

В Java соглашение:

  • Объявите защищенное поле и реализуйте общедоступный, доступный только для чтения метод (метод) получения.

Какая идиома у Swift?

Джаспер Блюз
источник

Ответы:

219

Учитывая свойство класса, вы можете указать другой уровень доступа, добавив к объявлению свойства модификатор доступа, за которым следует getили setмежду скобками. Например, свойство класса с публичным получателем и частным установщиком будет объявлено как:

private(set) public var readonlyProperty: Int

Рекомендуемая литература: геттеры и сеттеры

Соображения Мартина об уровне доступности по-прежнему актуальны - то есть нет protectedмодификатора, internalограничивает доступ только к модулю, только privateк текущему файлу и publicбез ограничений.

Swift 3 примечания

2 новые модификаторы доступа, fileprivateи openбыли добавлены к языку, в то время как privateи publicбыли немного изменены:

  • openприменяется только к классу и членам класса: он используется, чтобы разрешить создание подкласса или переопределение члена за пределами модуля, в котором они определены. publicвместо этого делает класс или член общедоступным, но не наследуемым или переопределяемым

  • privateтеперь делает член видимым и доступным только из включающего объявления, тогда как fileprivateдля всего файла, в котором он содержится

Подробнее здесь .

Антонио
источник
Ницца! (Я позволил себе добавить varключевое слово missing, чтобы оно скомпилировалось.)
Мартин Р.
о, спасибо :) Обычно я копирую с детской площадки и вставляю, но на этот раз я, вероятно, сделал это неправильно.
Антонио
10
Обратите внимание, что по состоянию на январь 2015 года этот синтаксис не совсем правильный, если внешний класс не является public- он должен быть internalили вообще ничего (по умолчанию используется любой класс - publicили internal) - то естьprivate(set) var readonlyProperty: Int
Grimxn
1
Что ж, синтаксис правильный, учитывая, что прямо перед кодом я написал свойство класса с общедоступным геттером и частным сеттером - это просто пример. Но да, модификаторы доступа для свойств должны быть «совместимы» с модификатором доступа class / struct.
Антонио
Что касается последнего абзаца, я предполагаю, что это изменилось с тех пор, как был написан ответ, но privateтеперь он ограничивается текущим объявлением (не файлом) и fileprivateдоступен для ограничения текущим файлом. Также publicимеет некоторые ограничения и openне требуется никаких ограничений. Подробности здесь .
Найджел Б. Пек
2

Согласно @Antonio, мы можем использовать одно свойство для доступа к readOnlyзначению свойства публично и readWriteконфиденциально. Ниже моя иллюстрация:

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)")

И вот результат:

  Initial  valule: 10
  After increment method call: 11
  After decrement method call: 10
Сантош
источник