Швидко читайте лише зовнішнє, переписуйте внутрішню властивість


103

У Swift, що є звичайним способом визначення загальної структури, коли властивість має бути зовнішньо прочитаною, але внутрішньо модифікованою класом (та підкласами), яким вона володіє.

У Objective-C є такі варіанти:

  • Заявіть про властивість як прочитане лише в інтерфейсі та використовуйте розширення класу для доступу до ресурсу внутрішньо. Це доступ на основі повідомлень, отже, він добре працює з KVO, атомністю тощо.
  • Заявіть про властивість як прочитане лише в інтерфейсі, але отримайте доступ до резервного ivar внутрішньо. Оскільки доступ до ivar за замовчуванням захищений, це непогано працює в ієрархії класів, де підкласи також зможуть змінювати значення, але поле в іншому випадку читається тільки.

У Java умовою є:

  • Оголосити захищене поле та запровадити загальнодоступний доступ (лише для читання).

Яка ідіома Свіфта?

Відповіді:


219

З огляду на властивість класу, ви можете вказати інший рівень доступу, префіксуючи декларацію властивості за допомогою модифікатора доступу з подальшим getабо setміж дужками. Наприклад, властивість класу з публічним getter та приватним сеттером буде оголошено як:

private(set) public var readonlyProperty: Int

Пропоноване читання: Getters and Setters

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

Швидкий 3 нотатки

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

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

  • privateтепер робить член видимим і доступним лише із додаючої декларації, тоді як fileprivateдо всього файлу, де він міститься

Детальніше тут .


Приємно! (Я маю на себе сміливо додати пропущене varключове слово, щоб його скласти.)
Martin R

о, велике спасибі :) Я зазвичай копіюю з майданчика і вставляю, але цього разу, мабуть, зробив це неправильно.
Антоніо

10
Зауважимо, на січень-2015 цей синтаксис не зовсім правильний, якщо зовнішній клас не є public- він повинен бути internalабо взагалі нічого (що за замовчуванням для будь-якого класу - publicабо internal) - тобтоprivate(set) var readonlyProperty: Int
Grimxn

1
Добре синтаксис правильний, враховуючи, що безпосередньо перед кодом я написав властивість класу з публічним getter та приватним сеттером - це лише приклад. Але так, модифікатори доступу для властивостей повинні бути "сумісними" з модифікатором доступу класу / структура.
Антоніо

Щодо останнього абзацу, я думаю, це змінилося з часу написання відповіді, але 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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.