Cepat baca eksternal, baca-tulis properti internal

103

Di Swift, apa cara konvensional untuk menentukan pola umum di mana properti menjadi hanya dapat dibaca secara eksternal, tetapi dapat dimodifikasi secara internal oleh kelas (dan subkelas) yang memilikinya.

Di Objective-C, ada opsi berikut:

  • Deklarasikan properti sebagai hanya-baca di antarmuka dan gunakan ekstensi kelas untuk mengakses properti secara internal. Ini adalah akses berbasis pesan, oleh karena itu berfungsi dengan baik dengan KVO, atomicity, dll.
  • Deklarasikan properti sebagai hanya-baca di antarmuka, tetapi akses backing ivar secara internal. Karena akses default untuk ivar dilindungi, ini berfungsi dengan baik dalam hierarki kelas, di mana subkelas juga dapat mengubah nilainya, tetapi bidang ini hanya dapat dibaca.

Di Java konvensi adalah:

  • Deklarasikan bidang yang dilindungi, dan terapkan pengambil (metode) publik hanya-baca.

Apa idiom Swift?

Jasper Blues
sumber

Jawaban:

219

Dengan mempertimbangkan properti kelas, Anda dapat menentukan tingkat akses yang berbeda dengan memberi awalan deklarasi properti dengan pengubah akses diikuti dengan getatau di setantara tanda kurung. Misalnya, properti kelas dengan pengambil publik dan penyetel pribadi akan dideklarasikan sebagai:

private(set) public var readonlyProperty: Int

Bacaan yang disarankan: Getters and Setter

Pertimbangan Martin tentang tingkat aksesibilitas masih berlaku - yaitu tidak ada protectedpengubah, internalmembatasi akses ke modul saja, privateke file saat ini saja, dan publictanpa batasan.

Swift 3 catatan

2 pengubah akses baru, fileprivatedan opentelah ditambahkan ke bahasa, sementara privatedan publictelah sedikit diubah:

  • openberlaku untuk kelas dan hanya anggota kelas: ini digunakan untuk mengizinkan kelas menjadi subkelas atau anggota diganti di luar modul tempat mereka didefinisikan. publicalih-alih membuat kelas atau anggota dapat diakses publik, tetapi tidak dapat diwariskan atau diganti

  • privatesekarang membuat anggota terlihat dan dapat diakses dari deklarasi terlampir saja, sedangkan fileprivateke seluruh file di mana ia terkandung

Lebih lengkapnya di sini .

Antonio
sumber
Bagus! (Saya telah mengambil kebebasan untuk menambahkan varkata kunci yang hilang untuk membuatnya dikompilasi.)
Martin R
oh terima kasih banyak :) Saya biasanya menyalin dari playground dan paste, tapi kali ini saya mungkin salah melakukannya.
Antonio
10
Perhatikan pada Jan-2015 sintaks ini kurang tepat jika kelas luar tidak public- seharusnya internalatau tidak sama sekali (yang default ke kelas apa pun - publicatau internal) - yaituprivate(set) var readonlyProperty: Int
Grimxn
1
Nah sintaksnya benar dengan mempertimbangkan bahwa tepat sebelum kode saya menulis properti kelas dengan pengambil publik dan penyetel pribadi - ini hanya sebuah contoh. Tapi ya, pengubah akses untuk properti harus "kompatibel" dengan pengubah akses class / struct.
Antonio
Mengenai paragraf terakhir, saya kira ini telah berubah sejak jawabannya ditulis, tetapi privatesekarang membatasi ke deklarasi saat ini (bukan file) dan fileprivatetersedia untuk membatasi ke file saat ini. Juga publicmemang memiliki beberapa batasan dan opendiperlukan tanpa batasan. Detailnya di sini .
Nigel B. Peck
2

Sesuai @Antonio, kita dapat menggunakan satu properti untuk mengakses sebagai nilai readOnlyproperti secara publik dan readWritepribadi. Berikut ilustrasi saya:

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

Dan inilah hasilnya:

  Initial  valule: 10
  After increment method call: 11
  After decrement method call: 10
Santosh
sumber