Cara Membuat Salinan Dalam di Ruby

click fraud protection

Sering kali perlu untuk membuat salinan nilai dalam Ruby. Meskipun ini mungkin tampak sederhana, dan itu untuk objek sederhana, segera setelah Anda harus membuat salinan data struktur dengan banyak array atau hash pada objek yang sama, Anda akan dengan cepat menemukan banyak perangkap.

Objek dan Referensi

Untuk memahami apa yang terjadi, mari kita lihat beberapa kode sederhana. Pertama, operator penugasan menggunakan tipe POD (Data Lama Biasa) di Rubi.

a = 1
b = a
a + = 1
menempatkan b

Di sini, operator penugasan membuat salinan nilai Sebuah dan menugaskannya untuk b menggunakan operator penugasan. Perubahan apa pun pada Sebuah tidak akan tercermin dalam b. Tetapi bagaimana dengan sesuatu yang lebih kompleks? Pertimbangkan ini.

a = [1,2]
b = a
a << 3
menempatkan b.inspect

Sebelum menjalankan program di atas, coba tebak akan seperti apa hasilnya dan mengapa. Ini tidak sama dengan contoh sebelumnya, perubahan dibuat untuk Sebuah tercermin dalam b, tapi kenapa? Ini karena Himpunan objek bukan tipe POD. Operator penugasan tidak membuat salinan nilai, ia hanya menyalin

instagram viewer
referensi ke objek Array. Itu Sebuah dan b variabel sekarang referensi ke objek Array yang sama, perubahan apa pun di salah satu variabel akan terlihat di yang lain.

Dan sekarang Anda dapat melihat mengapa menyalin objek non-sepele dengan referensi ke objek lain bisa rumit. Jika Anda hanya membuat salinan dari objek, Anda hanya menyalin referensi ke objek yang lebih dalam, jadi salinan Anda disebut sebagai "salinan dangkal."

Apa yang Ruby Sediakan: dup dan klon

Ruby memang menyediakan dua metode untuk membuat salinan objek, termasuk satu yang dapat dilakukan untuk membuat salinan yang dalam. Itu Objek # dup Metode akan membuat salinan objek yang dangkal. Untuk mencapai ini, para dup metode akan memanggil initialize_copy metode kelas itu. Apa yang dilakukan ini tergantung pada kelas. Di beberapa kelas, seperti Array, ia akan menginisialisasi array baru dengan anggota yang sama dengan array asli. Namun, ini bukan salinan yang mendalam. Pertimbangkan yang berikut ini.

a = [1,2]
b = a.dup
a << 3
menempatkan b.inspect
a = [[1,2]]
b = a.dup
a [0] << 3
menempatkan b.inspect

Apa yang terjadi di sini? Itu Array # initialize_copy Metode memang akan membuat salinan dari Array, tetapi salinan itu sendiri merupakan salinan yang dangkal. Jika Anda memiliki tipe non-POD lain dalam array Anda, gunakan dup hanya akan menjadi salinan sebagian dalam. Ini hanya akan sedalam array pertama, lebih dalam array, hash atau objek lain hanya akan disalin dangkal.

Ada metode lain yang layak disebut, klon. Metode klon melakukan hal yang sama seperti dup dengan satu perbedaan penting: diharapkan objek akan menimpa metode ini dengan metode yang dapat menyalin dalam-dalam.

Jadi dalam prakteknya apa artinya ini? Ini berarti setiap kelas Anda dapat menentukan metode klon yang akan membuat salinan yang mendalam dari objek itu. Ini juga berarti Anda harus menulis metode kloning untuk setiap kelas yang Anda buat.

A Trick: Marshalling

"Marshalling" suatu objek adalah cara lain untuk mengatakan "membuat cerita bersambung" suatu objek. Dengan kata lain, ubah objek itu menjadi aliran karakter yang dapat ditulis ke file yang Anda bisa "tidak menciptakan" atau "membatalkan registrasi" nanti untuk mendapatkan objek yang sama. Ini dapat dimanfaatkan untuk mendapatkan salinan mendalam dari objek apa pun.

a = [[1,2]]
b = Marshal.load (Marshal.dump (a))
a [0] << 3
menempatkan b.inspect

Apa yang terjadi di sini? Marshal.dump membuat "dump" dari array bersarang disimpan di Sebuah. Dump ini adalah string karakter biner yang dimaksudkan untuk disimpan dalam file. Ini merumahkan isi penuh array, salinan lengkap yang mendalam. Lanjut, Marshal.load melakukan yang sebaliknya. Ini mem-parsing array karakter biner ini dan menciptakan Array yang sama sekali baru, dengan elemen Array yang sama sekali baru.

Tapi ini tipuan. Ini tidak efisien, tidak akan bekerja pada semua objek (apa yang terjadi jika Anda mencoba mengkloning koneksi jaringan dengan cara ini?) Dan mungkin tidak terlalu cepat. Namun, ini adalah cara termudah untuk membuat salinan yang dalam dari kustom initialize_copy atau klon metode. Juga, hal yang sama dapat dilakukan dengan metode suka to_yaml atau to_xml jika Anda memiliki perpustakaan yang dimuat untuk mendukungnya.

instagram story viewer