คุณรู้ไหมว่าคุณสามารถคัดลอกออบเจ็กต์ใน Ruby ได้? ไม่ chỉนั้น แตยังมีสองเมธอดที่แตกต่างกันสำหรับทำสิ่งนี้!
เมธอดเหล่านี้คือ:
dupclone
เราจะสำรวจความต่างในหนึ่งพัก แตก่อน...
ทำไมคุณถึงอยาก clone ออบเจ็กต์?
ออบเจ็กต์หลายอย่างใน Ruby เป็น mutable (เปลี่ยนแปลงได้)
หากคุณต้องการเปลี่ยนออบเจ็กต์ แต ต้องการเก็บสำเนาต้นฉบับไว้ คุณสามารถ clone มันได้
ตัวอย่าง.
คุณอาจอยากได้อาร์เรย์ที่มีทุกองค์ประกอบ ยกเว้นตัวแรก
วิธีหนึ่ง:
a = [1,2,3,4,5] a[1..-1] # [2,3,4,5]
อีกวิธี:
b = a.clone b.shift # [1] b # [2,3,4,5]
ทั้งสองตัวอย่างช่วยให้คุณเก็บอาร์เรย์ต้นฉบับไว้ได้

Frozen Objects (ออบเจ็กต์ที่ถูกแช่แข็ง)
Dup และ clone ไม่ใช่ alias ของกันและกันเหมือนเมธอด Ruby อื่นๆ (map/collect) มีความต่างเล็กน้อยระหว่างพวกมัน
การสำรวจ ความเหมือนและความต่าง ระหว่างสองสิ่ง คือ วิธีที่ดีในการปรับปรุงความเข้าใจ
ทั้งสองเมธอดคัดลอกออบเจ็กต์ ความต่างคือ dup ไม่คัดลอกแอตทริบิวต์ของออบเจ็กต์
อะไรคือแอตทริบิวต์ของออบเจ็กต์?
- frozen status (สถานะการแช่แข็ง)
- tainted status (สถานะที่ปนเปื้อน)
- singleton class
ตัวอย่าง:
a = Object.new.freeze b = a.dup b.frozen? # false b = a.clone b.frozen? # true
Ruby 2.4 รวมตัวเลือกสำหรับ clone เพื่อเพิกเฉยสถานะ frozen ของออบเจ็กต์ที่ clone
ตัวอย่าง:
a.clone(freeze: true) a.clone(freeze: false)
Deep vs Shallow Copying
การคัดลอกออบเจ็กต์มีรายละเอียดมากกว่าที่คิด
เมื่อคุณทำสำเนา ด้วย dup หรือ clone คุณกำลังทำ shallow copy
นี่หมายความว่าออบเจ็กต์ที่อยู่ภายในออบเจ็กต์อื่น จะไม่ถูกคัดลอก
กล่าวอีกนัยหนึ่ง:
ถ้าคุณมีอาร์เรย์ของสตริง แค่อาร์เรย์จะถูกคัดลอก ไม่ใช่สตริงเอง
ดูด้วยตัวเอง:
original = %w(apple orange banana) copy = original.clone original.map(&:object_id) # [23506500, 23506488, 23506476] copy.map(&:object_id) # [23506500, 23506488, 23506476]
Object IDs เหมือนกันแม้หลัง clone อาร์เรย์ ดังนั้นเรามีสตริงเดียวกัน
คุณแก้ได้ด้วย:
strings.clone.map(&:clone)
สิ่งนี้ทำให้ทั้งอาร์เรย์และสตริงถูก clone แตสังเกตว่านี้ไปได้แค่ระดับเดียว (one level deep) คุณลอง deep_dup method จาก ActiveSupport เป็นทางเลือก
สรุป
คุณได้เรียนรู้เกี่ยวกับการ clone ออบเจ็กต์ใน Ruby! รวมถึงความต่างระหว่าง dup และ clone methods และ shallow copy vs deep copy
ขอบคุณที่อ่านครับ!