Swift readonly external, readwrite internal property


103

In Swift, qual è il modo convenzionale per definire il modello comune in cui una proprietà deve essere di sola lettura esternamente, ma modificabile internamente dalla classe (e dalle sottoclassi) che la possiedono.

In Objective-C, ci sono le seguenti opzioni:

  • Dichiarare la proprietà come di sola lettura nell'interfaccia e utilizzare un'estensione di classe per accedere alla proprietà internamente. Questo è un accesso basato sui messaggi, quindi funziona bene con KVO, atomicità, ecc.
  • Dichiarare la proprietà come di sola lettura nell'interfaccia, ma accedere internamente al supporto ivar. Poiché l'accesso predefinito per un ivar è protetto, funziona bene in una gerarchia di classi, dove anche le sottoclassi saranno in grado di modificare il valore, ma il campo è altrimenti di sola lettura.

In Java la convenzione è:

  • Dichiarare un campo protetto e implementare un getter (metodo) pubblico di sola lettura.

Qual è l'idioma di Swift?

Risposte:


219

Data una proprietà di classe, è possibile specificare un diverso livello di accesso anteponendo alla dichiarazione della proprietà il modificatore di accesso seguito da geto settra parentesi. Ad esempio, una proprietà di classe con un getter pubblico e un setter privato verrà dichiarata come:

private(set) public var readonlyProperty: Int

Letture consigliate: Getters e Setters

Le considerazioni di Martin sul livello di accessibilità sono ancora valide - cioè non c'è un protectedmodificatore, internallimita l'accesso solo al modulo, solo privateal file corrente e publicsenza restrizioni.

Swift 3 note

2 nuovi modificatori di accesso fileprivatee opensono stati aggiunti alla lingua, mentre privatee publicsono stati leggermente modificati:

  • opensi applica solo alla classe e ai membri della classe: viene utilizzata per consentire a una classe di essere sottoclasse o di sostituire un membro al di fuori del modulo in cui sono definiti. publicrende invece la classe o il membro pubblicamente accessibile, ma non ereditabile o sovrascrivibile

  • privateora rende un membro visibile e accessibile solo dalla dichiarazione allegata, mentre fileprivateper l'intero file in cui è contenuto

Maggiori dettagli qui .


Bello! (Mi prendo la libertà di aggiungere la varparola chiave mancante per compilarla.)
Martin R

oh grazie mille :) Di solito copio da playground e incollo, ma questa volta probabilmente ho sbagliato.
Antonio

10
Nota a partire da gennaio 2015 questa sintassi non è del tutto corretta se la classe esterna non è public- dovrebbe essere internalo niente (che per impostazione predefinita è qualunque sia la classe - publico internal) - cioèprivate(set) var readonlyProperty: Int
Grimxn

1
Ebbene, la sintassi è corretta tenendo conto del fatto che subito prima del codice ho scritto una proprietà di classe con un getter pubblico e un setter privato - è solo un esempio. Ma sì, i modificatori di accesso per le proprietà devono essere "compatibili" con il modificatore di accesso class / struct.
Antonio

Per quanto riguarda l'ultimo paragrafo, immagino che questo sia cambiato da quando è stata scritta la risposta, ma privateora si limita alla dichiarazione corrente (non al file) ed fileprivateè disponibile per la limitazione al file corrente. Inoltre publicha alcune restrizioni ed openè necessario per nessuna restrizione. Dettagli qui .
Nigel B. Peck

2

Come per @Antonio, possiamo utilizzare una singola proprietà per accedere come readOnlyvalore della proprietà pubblicamente e readWriteprivatamente. Di seguito è la mia illustrazione:

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

Ed ecco l'output:

  Initial  valule: 10
  After increment method call: 11
  After decrement method call: 10
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.