Membawa Kepalaku Berputar

13

Saya baru mengenal pemrograman berorientasi objek, dan satu konsep yang telah lama saya pahami adalah kekekalan. Saya pikir bola lampu padam tadi malam tapi saya ingin memverifikasi:

Ketika saya menemukan pernyataan bahwa objek tidak dapat diubah tidak dapat diubah, saya bingung karena saya dapat, misalnya, melakukan hal berikut:

NSString *myName = @"Bob";
myName = @"Mike";

Di sana, saya baru saja mengubah myName, dari tipe NSString yang tidak dapat diubah. Masalah saya adalah bahwa kata, "objek" dapat merujuk ke objek fisik dalam memori, atau abstraksi, "myName." Definisi sebelumnya berlaku untuk konsep kekekalan.

Sedangkan untuk variabel, definisi imutabilitas yang lebih jelas (bagi saya) adalah bahwa nilai objek yang tidak dapat diubah hanya dapat diubah dengan juga mengubah lokasinya dalam memori, yaitu referensi (juga dikenal sebagai penunjuknya).

Apakah ini benar, atau apakah saya masih tersesat di hutan?

Michael Mangold
sumber
13
Tipe Anda bukan NSString, itu " penunjuk ke dan NSString", yang tidak dapat diubah. Aku tahu apa-apa tentang C objektif, tapi aku menebak dalam contoh Anda yang @"Mike"menciptakan contoh baru dari NSStringdan menugaskan ke pointer , myName. Jadi Anda belum mengubah objek yang myNamemenunjuk, hanya apa yang menunjuk.
fwgx
2
@ fwgx Masukkan sebagai jawaban dan Anda akan mendapatkan upvote saya.
Gulshan
Terima kasih semuanya atas semua balasannya, mereka sangat membantu. Saya sekarang mengerti bahwa objek yang tidak dapat diubah adalah nilai dalam memori, bukan variabel yang menunjuk padanya.
Michael Mangold
@Gulshan Selesai, lihat di bawah ....
fwgx
Untuk memahami kekekalan, saya sarankan untuk belajar bahasa pemrograman yang dengan jelas memisahkan pengikatan (yaitu memberikan nama ke objek) dengan kemampuan berubah-ubah (yaitu memungkinkan nama untuk dipindahkan ke objek yang berbeda). ML (dalam kedok apa pun: SML, Ocaml, F #) adalah contoh yang baik.
Gilles 'SO- berhenti menjadi jahat'

Jawaban:

4

Sepertinya Anda sedang menuju ke arah yang benar, tetapi belum mendapatkannya. Ini salah:

Di sana, saya baru saja mengubah myName, dari tipe NSString yang tidak dapat diubah. Masalah saya adalah bahwa kata, "objek" dapat merujuk ke objek fisik dalam memori, atau abstraksi, "myName."

Dalam cuplikan kode Anda, myNamebukan dari tipe yang tidak dapat diubah NSString, itu adalah tipe yang dapat berubahNSString* (pointer ke NSString). Kedengarannya seperti hal utama yang Anda lewatkan adalah untuk memahami bahwa pointer hanyalah nilai lain , dan memiliki kehidupan yang benar-benar terpisah dari hal yang ditunjuknya (atau benda, jika Anda mengubahnya sebagian jalan selama masa pakainya).

Kamu bilang:

... nilai objek yang tidak dapat diubah hanya dapat diubah dengan juga mengubah lokasinya dalam memori, yaitu referensi (juga dikenal sebagai penunjuknya).

Ini salah. Objek tidak memiliki pointer yang menunjuk ke sana, juga tidak ada lokasi memori objek yang dikendalikan atau dipengaruhi oleh pointer ke sana.

Jadi, dua NSStringobjek dalam contoh Anda ( @"Bob"dan @"Mike") benar-benar terpisah dari myNamevariabel. Mereka juga benar-benar terpisah satu sama lain. Ketika Anda mengubah myNameke menunjuk ke @"Mike"bukannya menunjuk ke @"Bob", Anda tidak mengubah NSStringobjek.


Untuk kelengkapan, saya akan perhatikan bahwa pemulung membuat ini lebih rumit karena perubahan pada pointer dapat mempengaruhi objek yang mereka tuju (ed). Namun, ini adalah detail implementasi yang seharusnya tidak mempengaruhi perilaku kode yang dapat diamati.

John Bartholomew
sumber
17

Anda tersesat pada kata-kata. Kekekalan berarti: Selama Anda tidak mengubah variabel, itu akan selalu "mengandung" nilai yang sama, tidak peduli apa yang Anda lakukan dengan variabel lain.

Contoh balik dalam C (sedikit disederhanakan, dengan asumsi arsitektur yang memungkinkan itu):

 char *a = "Hello World";
 char *b = a;
 b[0] = 'Y';

Sekarang tidak lagi "berisi" (yaitu menunjuk pada) string "Hello World", tapi itu "Yello World" sebagai gantinya.

Dalam bahasa di mana string tidak dapat diubah, seperti Java dan (EDIT: aman) C #, Anda tidak bisa melakukan itu. Tidak mungkin. Ini berarti bahwa setiap bagian dari program dapat dengan aman menyimpan referensi ke string dan mengandalkan bahwa isinya tidak pernah berubah; jika tidak, mereka harus membuat salinan hanya agar aman.

Tetapi variabel masih bisa berubah. Anda bisa membiarkannya menunjuk ke objek lain. Hanya saja benda itu sendiri tidak akan berubah di belakang Anda.

pengguna281377
sumber
1
Anda secara teknis dapat mengubah konten string dalam C #, Anda hanya perlu menggunakan unsafekode.
Aaronaught
1
Aaronaught: Terima kasih atas informasinya, Anda benar; untuk semua orang yang perlu tahu caranya: msdn.microsoft.com/en-us/library/ms228599.aspx
user281377
10

Anda membingungkan variabel dengan objek. Variabel dapat digunakan untuk menyimpan referensi ke objek, tetapi mereka BUKAN objek. Ini adalah objek yang tidak berubah, bukan variabel, jadi Anda bisa mengubah variabel dari satu objek ke objek lain, tetapi Anda tidak bisa mengubah atribut objek jika tidak berubah.

Pikirkan benda itu sebagai tetangga yang keras dan mabuk. Jika dia masuk akal (bisa berubah), Anda mungkin bisa mengetuk pintunya dan mengubahnya menjadi gaya hidup di mana dia tidak membuat banyak kebisingan. Tetapi jika ia tidak berubah, satu-satunya perubahan Anda adalah berharap bahwa orang lain masuk!

Kilian Foth
sumber
3
Saya memiliki beberapa tetangga yang saya ingin bisu.
Dave Nay
Saya pikir Anda tidak perlu contoh di paragraf kedua karena penjelasan Anda cukup baik. Contohnya IMO saja bisa membingungkan. Namun +1 untuk jawaban singkat untuk pertanyaan si kap.
Paul McCabe
@ DaveNay: Saya minta maaf untuk permainan kata-kata yang tersembunyi Tidak dimaksudkan sama sekali.
Kilian Foth
6

Variabel bukan objek. Variabel adalah nama, yang merujuk ke objek (atau lebih umum suatu nilai).

Misalnya "penjaga gawang" adalah nama yang kami gunakan untuk merujuk ke objek (orang) yang bertanggung jawab untuk mempertahankan tujuan. Tetapi jika saya mengganti orang itu dengan orang lain (karena mantan terluka atau yang lainnya), orang baru sekarang disebut sebagai "penjaga gawang".

Pernyataan penugasan adalah apa yang membuat variabel dapat berubah (beberapa bahasa, seperti Haskell tidak memilikinya dan pada kenyataannya menggunakan variabel yang tidak dapat diubah). Ini memungkinkan Anda untuk mendefinisikan kembali makna nama dan dengan demikian menetapkan kembali nilainya.

Sekarang benda itu sendiri tidak bisa berubah. Beberapa ribu tahun yang lalu orang bisa menganggap berlian tidak berubah. Apa pun yang Anda lakukan dengan berlian, Anda tidak dapat memodifikasinya. Apakah Anda menyebutnya waggawooga (secara longgar diterjemahkan menjadi "batu mengkilap terbesar suku kami") atau berhenti menyebutnya seperti itu (karena Anda menemukan yang lebih besar), intan tetap sama. Sebaliknya potongan kayu yang Anda gunakan untuk mengukir dalam gambar lucu dengan waggawooga Anda tidak tetap sama. Itu terbukti bisa berubah. Bahkan jika itu memiliki nama yang sama sepanjang waktu.

Baik variabel dan nilai-nilai dapat berubah (secara independen). Dalam hal ini, objeklah yang tidak bisa diubah. Setelah membuat NSString, Anda tidak dapat memodifikasinya. Anda bisa menyebutnya nama dan menyebarkannya, tetapi tetap sama. Berbeda dengan itu, NSMutableStringdapat diubah setelah pembuatan, misalnya dengan memanggil setStringmetode.

back2dos
sumber
Cinta perbandingan waggawooga!
Michael K
Hanya saja agar tidak membingungkan poster asli lebih dari yang diperlukan: meskipun poin Anda bahwa variabel bukan objek adalah baik, variabel sebenarnya tidak didefinisikan sebagai "nama yang merujuk pada nilai". Variabel mungkin dinamai, dan merujuk ke lokasi penyimpanan yang berisi nilai. Dalam banyak bahasa pemrograman, variabel tidak perlu dinamai, dan dalam banyak bahasa variabel yang sama dapat memiliki lebih dari satu nama.
Eric Lippert
4

Saya pikir Anda merasa bingung, karena Anda mencampurkan dua konsep: objek itu sendiri dan nama variabel terikat ke objek itu.

Objek yang tidak dapat diubah tidak dapat diubah. Titik. Namun, nama variabel (simbol) terikat ke objek yang tidak dapat diubah, dapat dimodifikasi untuk terikat ke objek lain yang tidak dapat diubah.

Dengan kata lain, apa yang Anda lakukan dalam dua baris ini adalah:

  1. buat objek string yang tidak berubah dengan nilai "Bob"
  2. ikat simbol myNameke objek itu
  3. buat objek string yang tidak berubah dengan nilai "Mike"
  4. ikat simbol myNameke objek itu
vartec
sumber
2

Jenis Anda Anda bukan NSString, itu adalah " pointer ke sebuah NSString", yang tidak berubah. Saya tidak tahu apa-apa tentang tujuan C, tapi saya menduga dalam contoh Anda yang @"Mike"membuat contoh baru NSStringdan menugaskannya ke pointer myName . Jadi Anda tidak berubah objek yang myNamesedang menunjuk ke, hanya apa itu menunjuk.

fwgx
sumber
0

Berikut adalah contoh objek yang bisa berubah: array chardalam C:

char str[10];

Aku dapat mengubah isi dari struntuk isi hati saya (selama itu tidak lebih dari 10 karakter). Agar dapat dikenali sebagai string oleh fungsi pustaka string C, harus ada trailing 0, sehingga dapat menyimpan string hingga 9 karakter:

strcpy(str, "hello"); // str now contains the string "hello\0"
strcpy(str, "world"); // str now contains the string "world\0"

str[0] = 'W';         // str now contains "World\0"

und jadi weiter .

Bandingkan ini dengan objek string di Jawa:

String foo = "Hello";

String contoh (bongkahan memori yang berisi karakter 'H', 'e', 'l', 'l', dan 'o') tidak dapat dimodifikasi; Saya tidak dapat mengubah konten string itu. Ketika Anda menulis sesuatu seperti

foo = foo + " World";

Anda tidak menambahkan "Dunia" ke akhir instance "Halo"; Anda membuat instance baru , menyalin "Hello World" ke sana, dan memperbarui foountuk merujuk ke instance string baru itu.

footidak sendiri berisi instance string; itu hanya merujuk ke instance itu (mirip dengan pointer di C atau Obj-C), maka mengapa tipe seperti String disebut tipe referensi.

John Bode
sumber