Atribut mutabilitas ditandai pada penyimpanan (konstanta atau variabel), bukan tipe. Anda dapat berpikir struct memiliki dua mode: bisa berubah dan tidak bisa diubah . Jika Anda menetapkan nilai struct ke penyimpanan yang tidak dapat diubah (kami menyebutnya let
atau konstan di Swift), nilainya menjadi mode yang tidak dapat diubah, dan Anda tidak dapat mengubah status apa pun dalam nilai. (termasuk memanggil metode mutasi apa pun)
Jika nilai ditetapkan ke penyimpanan yang bisa berubah (kami menyebutnya var
atau variabel di Swift), Anda bebas untuk mengubah statusnya, dan pemanggilan metode mutasi diperbolehkan.
Selain itu, kelas tidak memiliki mode yang tidak dapat diubah / dapat diubah ini. IMO, ini karena kelas biasanya digunakan untuk mewakili entitas yang dapat direferensikan . Dan entitas yang dapat memiliki referensi biasanya dapat berubah karena sangat sulit untuk membuat dan mengelola grafik referensi dari entitas dengan cara yang tidak dapat diubah dengan kinerja yang tepat. Mereka dapat menambahkan fitur ini nanti, tetapi setidaknya tidak sekarang.
Untuk programmer Objective-C, konsep yang bisa berubah / tidak berubah sangat familiar. Di Objective-C kami memiliki dua kelas yang terpisah untuk setiap konsep, tetapi di Swift, Anda dapat melakukan ini dengan satu struct. Setengah kerja.
Untuk programmer C / C ++, ini juga merupakan konsep yang sangat familiar. Inilah yang const
dilakukan kata kunci di C / C ++.
Selain itu, nilai yang tidak dapat diubah dapat dioptimalkan dengan sangat baik. Secara teori, pengompilasi Swift (atau LLVM) dapat melakukan penghapusan salinan pada nilai-nilai yang diteruskan let
, seperti di C ++. Jika Anda menggunakan struct immutable dengan bijak, itu akan mengungguli kelas refcount.
Memperbarui
Karena @Joseph mengklaim ini tidak menjelaskan alasannya , saya menambahkan sedikit lagi.
Struktur memiliki dua jenis metode. metode polos dan mutasi . Metode biasa menyiratkan tidak dapat diubah (atau tidak bermutasi) . Pemisahan ini hanya ada untuk mendukung semantik yang tidak dapat diubah . Objek dalam mode yang tidak dapat diubah tidak boleh mengubah statusnya sama sekali.
Kemudian, metode yang tidak dapat diubah harus menjamin keabadian semantik ini . Artinya tidak boleh mengubah nilai internal apa pun. Jadi compiler tidak mengizinkan perubahan status apa pun dengan sendirinya dalam metode yang tidak dapat diubah. Sebaliknya, metode mutasi bebas untuk mengubah status.
Dan kemudian, Anda mungkin memiliki pertanyaan mengapa tidak berubah adalah default? Itu karena sangat sulit untuk memprediksi keadaan mutasi nilai di masa depan, dan itu biasanya menjadi sumber utama sakit kepala dan bug. Banyak orang setuju bahwa solusinya adalah menghindari hal-hal yang dapat berubah, dan kemudian tidak dapat diubah secara default berada di atas daftar keinginan selama beberapa dekade dalam bahasa keluarga C / C ++ dan turunannya.
Lihat gaya fungsional murni untuk lebih jelasnya. Bagaimanapun, kita masih membutuhkan barang yang bisa berubah karena barang yang tidak bisa diubah memiliki beberapa kelemahan, dan membahasnya sepertinya di luar topik.
Saya harap ini membantu.
const
metode jika Anda ingin memiliki 'const this' dan diizinkan pada instance konstan (metode normal tidak dapat digunakan jika instance adalah const). Swift melakukan hal yang sama dengan default kebalikan: sebuah metode memiliki 'const this' secara default dan Anda menandainya sebaliknya jika harus dilarang untuk instance konstan.Struktur adalah kumpulan bidang; jika contoh struktur tertentu dapat berubah, bidangnya akan dapat berubah; jika sebuah instance tidak dapat diubah, bidangnya akan tetap. Oleh karena itu, tipe struktur harus disiapkan untuk kemungkinan bahwa bidang contoh tertentu dapat berubah atau tidak berubah.
Agar metode struktur dapat mengubah bidang dari struct yang mendasari, bidang tersebut harus bisa berubah. Jika metode yang mengubah bidang dari struct yang mendasarinya dipanggil pada struktur yang tidak dapat diubah, itu akan mencoba untuk mengubah bidang yang tidak dapat diubah. Karena tidak ada hal baik yang datang dari itu, doa seperti itu perlu dilarang.
Untuk mencapai itu, Swift membagi metode struktur menjadi dua kategori: metode yang memodifikasi struktur yang mendasarinya, dan dengan demikian hanya dapat dipanggil pada contoh struktur yang dapat berubah, dan yang tidak mengubah struktur yang mendasarinya dan karenanya harus dapat dipanggil pada contoh yang dapat berubah dan tidak dapat diubah . Penggunaan terakhir mungkin lebih sering, dan dengan demikian menjadi default.
Sebagai perbandingan, .NET saat ini (masih!) Tidak menawarkan cara untuk membedakan metode struktur yang memodifikasi struktur dari yang tidak. Sebaliknya, memanggil metode struktur pada instance struktur yang tidak dapat diubah akan menyebabkan compiler membuat salinan yang dapat diubah dari instance struktur, membiarkan metode melakukan apa pun yang diinginkan dengannya, dan membuang salinan tersebut ketika metode tersebut selesai. Ini memiliki efek memaksa compiler membuang waktu untuk menyalin struktur apakah metode memodifikasinya atau tidak, meskipun menambahkan operasi penyalinan hampir tidak akan pernah mengubah apa yang semantik kode salah menjadi kode yang benar secara semantik; itu hanya akan menyebabkan kode yang salah secara semantik dalam satu cara (memodifikasi nilai "tetap") menjadi salah dengan cara yang berbeda (memungkinkan kode untuk berpikir itu memodifikasi struktur, tetapi membuang perubahan yang dicoba). Mengizinkan metode struct untuk menunjukkan apakah mereka akan memodifikasi struktur yang mendasarinya dapat menghilangkan kebutuhan akan operasi penyalinan yang tidak berguna, dan juga memastikan bahwa percobaan penggunaan yang salah akan ditandai.
sumber
Perhatian: istilah awam di depan.
Penjelasan ini tidak sepenuhnya benar pada tingkat kode yang paling rumit. Namun itu telah ditinjau oleh seorang pria yang benar-benar bekerja pada Swift dan dia mengatakan itu cukup bagus sebagai penjelasan dasar.
Jadi saya ingin mencoba menjawab pertanyaan "mengapa" secara sederhana dan langsung .
Tepatnya: mengapa kita harus menandai fungsi struct seperti
mutating
ketika kita dapat mengubah parameter struct tanpa mengubah kata kunci?Jadi, gambaran besarnya, ini sangat berkaitan dengan filosofi yang membuat Swift cepat.
Anda dapat menganggapnya seperti masalah mengelola alamat fisik yang sebenarnya. Saat Anda mengubah alamat, jika ada banyak orang yang memiliki alamat Anda saat ini, Anda harus memberi tahu mereka semua bahwa Anda telah pindah. Tetapi jika tidak ada yang mengetahui alamat Anda saat ini, Anda dapat pindah ke mana pun Anda mau, dan tidak ada yang perlu tahu.
Dalam situasi ini, Swift seperti kantor pos. Jika banyak orang dengan banyak kontak sering berpindah-pindah, itu memiliki overhead yang sangat tinggi. Itu harus membayar banyak staf untuk menangani semua pemberitahuan itu, dan prosesnya memakan banyak waktu dan usaha. Itulah mengapa negara bagian Swift yang ideal adalah setiap orang di kotanya memiliki kontak sesedikit mungkin. Maka tidak perlu staf besar untuk menangani perubahan alamat, dan itu dapat melakukan segalanya dengan lebih cepat dan lebih baik.
Ini juga mengapa orang-orang Swift mengoceh tentang tipe nilai vs. tipe referensi. Secara alami, jenis referensi mengumpulkan "kontak" di semua tempat, dan jenis nilai biasanya tidak membutuhkan lebih dari pasangan. Jenis nilai adalah "Swift" -er.
Jadi kembali ke gambar kecil:
structs
. Struktur adalah masalah besar di Swift karena dapat melakukan sebagian besar hal yang dapat dilakukan objek, tetapi merupakan tipe nilai.Mari lanjutkan analogi alamat fisik dengan membayangkan a
misterStruct
yang hidupsomeObjectVille
. Analoginya sedikit miring di sini, tetapi saya pikir itu masih membantu.Jadi untuk memodelkan mengubah variabel pada a
struct
, katakanlahmisterStruct
memiliki rambut hijau, dan mendapat perintah untuk beralih ke rambut biru. Analoginya menjadi miring, seperti yang saya katakan, tetapi yang terjadi adalah bahwa alih-alih menggantimisterStruct
rambut, orang tua itu pindah dan orang baru dengan rambut biru masuk, dan orang baru itu mulai menyebut dirinya sendirimisterStruct
. Tidak ada yang perlu mendapatkan pemberitahuan perubahan alamat, tetapi jika ada yang melihat alamat itu, mereka akan melihat pria berambut biru.Sekarang mari kita buat model apa yang terjadi saat Anda memanggil fungsi di a
struct
. Dalam hal ini, sepertimisterStruct
mendapat perintah sepertichangeYourHairBlue()
. Jadi, kantor pos memberikan instruksi untukmisterStruct
"ganti rambut Anda menjadi biru dan beri tahu saya setelah selesai".Jika dia mengikuti rutinitas yang sama seperti sebelumnya, jika dia melakukan apa yang dia lakukan ketika variabel diubah secara langsung, yang
misterStruct
akan dilakukan adalah keluar dari rumahnya sendiri dan memanggil orang baru dengan rambut biru. Tapi itulah masalahnya.Perintah itu "go mengubah rambut Anda menjadi biru dan katakan ketika Anda sudah selesai," tapi itu adalah hijau orang yang mendapat perintah itu. Setelah pria biru itu pindah, notifikasi "pekerjaan selesai" masih harus dikirim kembali. Tapi pria biru itu tidak tahu apa-apa tentang itu.
[Untuk benar-benar memenangkan analogi ini sesuatu yang mengerikan, yang secara teknis terjadi pada pria berambut hijau adalah setelah dia pindah, dia segera bunuh diri. Jadi dia tidak bisa memberi tahu siapa pun bahwa tugasnya sudah selesai juga! ]
Untuk menghindari masalah ini, dalam kasus seperti ini saja , Swift harus masuk langsung ke rumah di alamat itu dan benar - benar mengganti rambut penghuni saat ini . Itu adalah proses yang sama sekali berbeda dari sekedar mengirim orang baru.
Dan itulah mengapa Swift ingin kami menggunakan
mutating
kata kunci!Hasil akhirnya terlihat sama untuk semua yang harus mengacu pada struktur: penghuni rumah sekarang berambut biru. Tetapi proses untuk mencapainya sebenarnya sangat berbeda. Sepertinya itu melakukan hal yang sama, tetapi melakukan hal yang sangat berbeda. Itu melakukan hal yang tidak pernah dilakukan oleh struktur Swift secara umum.
Jadi untuk memberikan sedikit bantuan kepada compiler yang buruk, dan tidak membuatnya harus mencari tahu apakah suatu fungsi bermutasi
struct
atau tidak, dengan sendirinya, untuk setiap fungsi struct yang pernah ada, kita diminta untuk mengasihani dan menggunakanmutating
kata kunci.Intinya, untuk membantu Swift tetap gesit, kita semua harus melakukan bagian kita. :)
EDIT:
Hei bung / dudette yang meremehkan saya, saya baru saja menulis ulang jawaban saya sepenuhnya . Jika Anda merasa lebih baik, apakah Anda akan menghapus suara negatifnya?
sumber
Struct Swift dapat dibuat sebagai konstanta (via
let
) atau variabel (viavar
)Pertimbangkan
Array
struct Swift (ya itu struct).Mengapa lampiran tidak berfungsi dengan nama planet? Karena append ditandai dengan
mutating
kata kunci. Dan karenaplanetNames
telah dideklarasikan menggunakanlet
, semua metode yang ditandai tersebut terlarang.Dalam contoh Anda, compiler dapat memberi tahu Anda sedang memodifikasi struct dengan menetapkan ke satu atau lebih propertinya di luar file
init
. Jika Anda mengubah sedikit kode Anda, Anda akan melihatnyax
dany
tidak selalu dapat diakses di luar struct. Perhatikanlet
di baris pertama.sumber
Pertimbangkan analogi dengan C ++. Metode struct di Swift menjadi
mutating
/ tidak-mutating
sama dengan metode di C ++ menjadi non-const
/const
. Metode yang ditandaiconst
dalam C ++ juga tidak dapat mengubah struct.Di C ++, Anda juga dapat "mengubah var dari luar struct" - tetapi hanya jika Anda memiliki
const
variabel non- struct. Jika Anda memilikiconst
variabel struct, Anda tidak dapat menetapkan ke var, dan Anda juga tidak dapat memanggilconst
metode non . Demikian pula, di Swift, Anda bisa mengubah properti struct hanya jika variabel struct bukan konstanta. Jika Anda memiliki konstanta struct, Anda tidak dapat menetapkan ke properti, dan Anda juga tidak dapat memanggilmutating
metode.sumber
Saya bertanya-tanya hal yang sama ketika saya mulai belajar Swift, dan masing-masing jawaban ini, sambil menambahkan beberapa wawasan mungkin, agak bertele-tele dan membingungkan. Saya rasa jawaban atas pertanyaan Anda sebenarnya cukup sederhana…
Metode mutasi yang didefinisikan di dalam struct Anda menginginkan izin untuk memodifikasi setiap instance dari dirinya sendiri yang akan pernah dibuat di masa depan. Bagaimana jika salah satu contoh tersebut ditetapkan ke konstanta yang tidak dapat diubah
let
? Uh oh. Untuk melindungi Anda dari diri Anda sendiri (dan untuk memberi tahu editor dan compiler apa yang Anda coba lakukan), Anda dipaksa untuk bersikap eksplisit ketika Anda ingin memberikan metode instance kekuatan semacam ini.Sebaliknya, setelan properti dari luar struct Anda beroperasi pada instance yang diketahui dari struct itu. Jika itu ditetapkan ke sebuah konstanta, Xcode akan memberi tahu Anda tentang hal itu saat Anda mengetik dalam pemanggilan metode.
Ini adalah salah satu hal yang saya sukai tentang Swift saat saya mulai lebih sering menggunakannya — waspada terhadap kesalahan saat saya mengetiknya. Tentu mengalahkan pemecahan masalah bug JavaScript yang tidak jelas!
sumber
SWIFT: Penggunaan fungsi mutasi di Structs
Pemrogram Swift mengembangkan Structs sedemikian rupa sehingga propertinya tidak dapat dimodifikasi dalam metode Struct. Misalnya, Periksa kode yang diberikan di bawah ini
Saat menjalankan kode di atas, kami mendapatkan kesalahan karena kami mencoba untuk menetapkan nilai baru ke populasi properti Kota Struct. Secara default, properti Structs tidak dapat dimutasi di dalam metodenya sendiri. Beginilah cara Pengembang Apple membuatnya, sehingga Structs akan memiliki sifat statis secara default.
Bagaimana kita mengatasinya? Apa alternatifnya?
Mutasi Kata Kunci:
Mendeklarasikan fungsi sebagai bermutasi di dalam Struct memungkinkan kita untuk mengubah properti di Structs. Baris No: 5, kode diatas berubah jadi seperti ini,
Sekarang kita dapat menetapkan nilai dari newpopulation untuk properti populasi ke dalam lingkup metode.
Catatan :
Jika kita menggunakan let sebagai ganti var untuk objek Struct, maka kita tidak dapat mengubah nilai properti apa pun, Juga ini adalah alasan mengapa kita mendapatkan kesalahan saat kita mencoba memanggil fungsi mutasi menggunakan let instance. Jadi lebih baik menggunakan var setiap kali Anda mengubah nilai properti.
Akan sangat senang mendengar komentar dan pemikiran Anda… ..
sumber