The Ruby docs untukdup
mengatakan:
Secara umum,
clone
dandup
mungkin memiliki semantik yang berbeda di kelas keturunan. Sementaraclone
digunakan untuk menduplikasi objek, termasuk keadaan internalnya,dup
biasanya menggunakan kelas objek turunan untuk membuat instance baru.
Tetapi ketika saya melakukan beberapa tes saya menemukan mereka sebenarnya sama:
class Test
attr_accessor :x
end
x = Test.new
x.x = 7
y = x.dup
z = x.clone
y.x => 7
z.x => 7
Jadi apa perbedaan antara kedua metode tersebut?
dup
dan apa yangclone
dilakukan, tetapi mengapa Anda akan menggunakan yang satu dan bukan yang lain.Jawaban:
Subclass dapat mengganti metode ini untuk memberikan semantik yang berbeda. Dalam
Object
dirinya sendiri, ada dua perbedaan utama.Pertama,
clone
menyalin kelas singleton, sementaradup
tidak.Kedua,
clone
mempertahankan kondisi beku, sementaradup
tidak.The pelaksanaan Rubinius untuk metode ini sering sumber saya untuk jawaban atas pertanyaan ini, karena cukup jelas, dan implementasi Ruby yang cukup compliant.
sumber
o = Object.new; class << o; A=5; end; puts ( class << o.clone; A; end ); puts ( class << o.dup; A; end )
.extend
diedit pada objek asli. JadiObject.new.extend(Enumerable).dup.is_a?(Enumerable)
mengembalikan salah.Ketika berhadapan dengan ActiveRecord ada perbedaan yang signifikan juga:
dup
membuat objek baru tanpa id yang ditetapkan, sehingga Anda dapat menyimpan objek baru ke database dengan menekan.save
clone
membuat objek baru dengan id yang sama, jadi semua perubahan yang dilakukan pada objek baru itu akan menimpa catatan asli jika memukul.save
sumber
dup
danclone
metode padaActiveRecord
objek saya , saya mendapatkan hasil terbalik dari apa yang Anda sebutkan dalam jawaban. yang berarti ketika saya menggunakandup
, itu menciptakan objek baru dengan ituid
sedang diatur dan saat menggunakannyaclone
menciptakan objek tanpa ituid
sedang diatur. dapatkah kamu memeriksanya kembali dan menjelaskan? . Thnxclone
apakah catatan baru yang belum pernah disimpan seharusnya cukup aman? Bisakah saya membuat "objek templat" dengan cara ini, dan mengkloningnya untuk menyimpan instance tertentu?Salah satu perbedaannya dengan benda beku. The
clone
benda beku juga beku (sedangkandup
dari objek beku tidak).Perbedaan lainnya adalah dengan metode tunggal. Kisah yang sama di sini,
dup
tidak menyalinnya, tetapiclone
juga.sumber
Keduanya hampir identik tetapi klon melakukan satu hal lebih dari dup. Dalam klon, keadaan beku objek juga disalin. Dalam dup, itu akan selalu dicairkan.
sumber
The doc yang lebih baru termasuk contoh yang baik:
sumber
Anda dapat menggunakan klon untuk melakukan pemrograman berbasis prototipe di Ruby. Kelas Obyek Ruby mendefinisikan metode klon dan metode dup. Baik klon dan dup menghasilkan salinan dangkal objek yang disalin; artinya, variabel instan objek disalin tetapi bukan objek yang dirujuk. Saya akan menunjukkan contoh:
Perhatikan pada contoh di atas, klon oranye menyalin keadaan (yaitu, variabel instance) dari objek apel, tetapi di mana objek apel referensi objek lain (seperti warna objek String), referensi tersebut tidak disalin. Sebaliknya, apel dan oranye sama-sama merujuk objek yang sama! Dalam contoh kita, referensi adalah objek string 'merah'. Ketika oranye menggunakan metode append, <<, untuk memodifikasi objek String yang ada, itu mengubah objek string menjadi 'oranye merah'. Efek ini juga mengubah apple.color, karena keduanya menunjuk ke objek String yang sama.
Sebagai catatan tambahan, operator penugasan, =, akan menetapkan objek baru dan karenanya menghancurkan referensi. Ini sebuah demonstrasi:
Dalam contoh di atas, ketika kami menetapkan objek baru ke metode instance warna klon oranye, itu tidak lagi merujuk objek yang sama seperti apel. Oleh karena itu, kita sekarang dapat memodifikasi metode warna oranye tanpa mempengaruhi metode warna apel, tetapi jika kita mengkloning objek lain dari apel, objek baru itu akan mereferensikan objek yang sama dalam variabel instance yang disalin seperti apel.
dup juga akan menghasilkan salinan dangkal dari objek yang disalin, dan jika Anda melakukan demonstrasi yang sama seperti ditunjukkan di atas untuk dup, Anda akan melihatnya bekerja dengan cara yang persis sama. Tetapi ada dua perbedaan utama antara clone dan dup. Pertama, seperti yang disebutkan orang lain, klon menyalin keadaan beku dan dup tidak. Apa artinya ini? Istilah 'beku' di Ruby adalah istilah esoterik untuk kekal, yang dengan sendirinya merupakan nomenklatur dalam ilmu komputer, yang berarti bahwa sesuatu tidak dapat diubah. Dengan demikian, objek beku di Ruby tidak dapat dimodifikasi dengan cara apa pun; itu, pada dasarnya, tidak berubah. Jika Anda mencoba mengubah objek yang dibekukan, Ruby akan memunculkan pengecualian RuntimeError. Karena klon menyalin keadaan beku, jika Anda mencoba untuk memodifikasi objek yang dikloning, itu akan meningkatkan pengecualian RuntimeError. Sebaliknya, karena dup tidak menyalin keadaan beku,
Kedua, dan, yang lebih menarik, mengkloning kelas singleton (dan karenanya metodenya)! Ini sangat berguna jika Anda ingin melakukan pemrograman berbasis prototipe di Ruby. Pertama, mari kita tunjukkan bahwa memang metode tunggal disalin dengan klon, dan kemudian kita bisa menerapkannya dalam contoh pemrograman berbasis prototipe di Ruby.
Seperti yang Anda lihat, kelas tunggal instance objek buah disalin ke klon. Dan karenanya objek yang dikloning memiliki akses ke metode singleton: seeded ?. Tapi ini tidak terjadi dengan dup:
Sekarang dalam pemrograman berbasis prototipe, Anda tidak memiliki kelas yang memperluas kelas lain dan kemudian membuat contoh kelas yang metodenya berasal dari kelas induk yang berfungsi sebagai cetak biru. Alih-alih, Anda memiliki objek dasar dan kemudian Anda membuat objek baru dari objek tersebut dengan metode dan statusnya disalin (tentu saja, karena kami sedang melakukan salinan dangkal melalui klon, objek apa pun yang referensi variabel instan akan dibagi seperti pada JavaScript prototipe). Anda kemudian dapat mengisi atau mengubah status objek dengan mengisi rincian metode yang dikloning. Dalam contoh di bawah ini, kami memiliki objek buah dasar. Semua buah memiliki biji, jadi kami membuat metode number_of_seeds. Tapi apel punya satu biji, jadi kami membuat klon dan mengisi detailnya. Sekarang ketika kita mengkloning apel, kita tidak hanya mengkloning metode tetapi kita mengkloning negara! Ingat klon melakukan salinan negara yang dangkal (variabel instan). Dan karena itu, ketika kita mengkloning apel untuk mendapatkan red_apple, red_apple akan secara otomatis memiliki 1 seed! Anda dapat menganggap red_apple sebagai objek yang mewarisi dari Apple, yang pada gilirannya mewarisi dari Buah. Karenanya, itulah sebabnya saya menggunakan huruf besar untuk Fruit and Apple. Kami menyingkirkan perbedaan antara kelas dan objek milik klon.
Tentu saja, kita dapat memiliki metode konstruktor dalam pemrograman berbasis protoype:
Pada akhirnya, menggunakan klon, Anda bisa mendapatkan sesuatu yang mirip dengan perilaku prototipe JavaScript.
sumber