Swift readonly external, внутреннее свойство readwrite

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

В Objective-C имеются следующие опции:

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

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

  • Объявить защищенное поле и реализовать общедоступный метод get-get-only-only.

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

Ответ 1

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

private(set) public var readonlyProperty: Int

Рекомендуемое чтение: Getters and Setters

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

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

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

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

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

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

Ответ 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