Szybka zewnętrzna właściwość tylko do odczytu, wewnętrzna właściwość do odczytu i zapisu

103

W języku Swift, jaki jest konwencjonalny sposób definiowania wspólnego wzorca, w którym właściwość ma być zewnętrznie tylko do odczytu, ale może być modyfikowana wewnętrznie przez klasę (i podklasy), które są jej właścicielami.

W Objective-C są następujące opcje:

  • Zadeklaruj właściwość jako tylko do odczytu w interfejsie i użyj rozszerzenia klasy, aby uzyskać dostęp do właściwości wewnętrznie. Jest to dostęp oparty na wiadomościach, dlatego dobrze współpracuje z KVO, atomowością itp.
  • Zadeklaruj właściwość jako tylko do odczytu w interfejsie, ale uzyskaj dostęp do zaplecza ivar wewnętrznie. Ponieważ domyślny dostęp do ivar jest chroniony, działa to dobrze w hierarchii klas, w której podklasy również będą mogły modyfikować wartość, ale w przeciwnym razie pole jest tylko do odczytu.

W Javie konwencja to:

  • Zadeklaruj chronione pole i zaimplementuj publiczną metodę pobierającą tylko do odczytu.

Jaki jest idiom dla Swift?

Jasper Blues
źródło

Odpowiedzi:

219

Mając właściwość klasy, można określić inny poziom dostępu, poprzedzając deklarację właściwości modyfikatorem dostępu, po którym następuje getlub setmiędzy nawiasami. Na przykład właściwość klasy z publicznym pobierającym i prywatnym ustawiaczem zostanie zadeklarowana jako:

private(set) public var readonlyProperty: Int

Sugerowana lektura: Getters and Setters

Rozważania Martina na temat poziomu dostępności są nadal aktualne - tj. Nie ma protectedmodyfikatora, internalogranicza dostęp tylko do modułu, tylko privatedo bieżącego pliku ipublic bez żadnych ograniczeń.

Szybkie 3 notatki

2 nowe modyfikatory dostępu fileprivatei openzostały dodane do języka, podczas gdy privatei publiczostały nieznacznie zmodyfikowane:

  • openma zastosowanie tylko do klas i składowych klas: służy do umożliwienia podklasy klasy lub zastąpienia elementu członkowskiego poza modułem, w którym są zdefiniowane. publiczamiast tego sprawia, że ​​klasa lub element członkowski są publicznie dostępne, ale nie są dziedziczone ani zastępowalne

  • privateteraz sprawia, że ​​element członkowski jest widoczny i dostępny tylko z załączającej deklaracji, podczas gdy fileprivatedo całego pliku, w którym się znajduje

Więcej szczegółów tutaj .

Antonio
źródło
Miły! (Pozwoliłem sobie dodać brakujące varsłowo kluczowe, aby je skompilować.)
Martin R
wielkie dzięki :) Zwykle kopiuję z placu zabaw i wklejam, ale tym razem chyba źle zrobiłem.
Antonio,
10
Zauważ, że od stycznia 2015 ta składnia nie jest całkiem poprawna, jeśli klasa zewnętrzna nie jest public- powinna być internallub wcale (która domyślnie jest taka, jaka jest - publiclub internal) - tj.private(set) var readonlyProperty: Int
Grimxn
1
Cóż, składnia jest poprawna, biorąc pod uwagę, że tuż przed kodem napisałem właściwość klasy z publicznym pobierającym i prywatnym ustawiaczem - to tylko przykład. Ale tak, modyfikatory dostępu do właściwości muszą być „zgodne” z modyfikatorem dostępu class / struct.
Antonio,
Jeśli chodzi o ostatni akapit, myślę, że zmieniło się to od czasu napisania odpowiedzi, ale privateteraz ogranicza się do bieżącej deklaracji (nie do pliku) i fileprivatejest dostępne do ograniczenia do bieżącego pliku. Również publicma pewne ograniczenia i openjest potrzebny do żadnych ograniczeń. Szczegóły tutaj .
Nigel B. Peck
2

Zgodnie z @Antonio, możemy użyć pojedynczej właściwości, aby uzyskać dostęp jako readOnlywartość właściwości publicznie i readWriteprywatnie. Poniżej moja ilustracja:

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

A oto wynik:

  Initial  valule: 10
  After increment method call: 11
  After decrement method call: 10
Santosh
źródło