คุณรู้หรือไม่ว่าคุณสามารถคัดลอกวัตถุใน Ruby ได้? ไม่เพียงเท่านั้น แต่ยังมีสองวิธีในการทำเช่นนี้!
วิธีการเหล่านี้ :
dup
clone
เราจะสำรวจความแตกต่างในอีกสักครู่ แต่ก่อนอื่น…
ทำไมคุณถึงต้องการโคลนวัตถุ ?
วัตถุจำนวนมากใน Ruby สามารถเปลี่ยนแปลงได้ คุณสามารถเปลี่ยนได้
หากคุณต้องการเปลี่ยนวัตถุแต่เก็บสำเนาต้นฉบับไว้ จากนั้นคุณสามารถโคลนได้
ตัวอย่างเช่น
คุณอาจต้องการอาร์เรย์ที่มีองค์ประกอบทั้งหมดยกเว้นองค์ประกอบแรก
วิธีหนึ่งในการทำสิ่งนี้ :
a =[1,2,3,4,5]a[1..-1]# [2,3,4,5]
อีกวิธีหนึ่งก็คือ :
b =a.cloneb.shift# [1]b# [2,3,4,5]
ทั้งสองตัวอย่างช่วยให้คุณสามารถเก็บอาร์เรย์เดิมไว้ได้
วัตถุแช่แข็ง
Dup &clone ไม่ใช่นามแฝงของกันและกันเหมือนกับที่เกิดขึ้นกับวิธี Ruby อื่น ๆ (แผนที่ / รวบรวม) ซึ่งมีความแตกต่างกันเล็กน้อย
สำรวจความเหมือนและความแตกต่าง ระหว่างสองสิ่งนี้ เป็นวิธีที่ดีในการปรับปรุงความเข้าใจของคุณ .
ทั้งสองวิธีคัดลอกวัตถุ ข้อแตกต่างคือ dup
ไม่คัดลอกแอตทริบิวต์ของวัตถุ
แอตทริบิวต์ของวัตถุใด
- สถานะหยุดนิ่ง
- สถานะเสีย
- ชั้นเดียว
นี่คือตัวอย่าง :
a =Object.new.freezeb =a.dupb.frozen?# falseb =a.cloneb.frozen?# จริง
Ruby 2.4 มีตัวเลือกสำหรับ clone
เพื่อละเว้นสถานะแช่แข็งของวัตถุที่ถูกโคลน
ตัวอย่าง :
a.clone(freeze:true)a.clone(freeze:false)
การคัดลอกแบบลึกและตื้น
การคัดลอกวัตถุมีมากกว่าที่คิด
เมื่อคุณทำสำเนาด้วย dup
หรือ clone
, คุณกำลังทำสำเนาที่ตื้น .
ซึ่งหมายความว่าระบบจะไม่คัดลอกวัตถุที่อยู่ในวัตถุอื่น
กล่าวอีกนัยหนึ่ง :
หากคุณมีอาร์เรย์ของสตริง ระบบจะคัดลอกเฉพาะอาร์เรย์เท่านั้น ไม่ใช่สตริงเอง
ดูด้วยตัวคุณเอง:
ต้นฉบับ =%w(กล้วยส้มแอปเปิ้ล)copy =original.cloneoriginal.map(&:object_id)# [23506500, 23506488, 23506476]copy.map(&:object_id)# [23506500, 23506488, 23506476]ก่อน>รหัสอ็อบเจ็กต์จะเหมือนกันแม้หลังจากโคลนอาร์เรย์แล้ว ดังนั้นเราจึงมีสตริงเดียวกัน
คุณแก้ได้ด้วยสิ่งนี้:
strings.clone.map(&:clone)ส่งผลให้ทั้งอาร์เรย์และสตริงถูกโคลน แต่สังเกตว่าการดำเนินการนี้ลึกเพียงระดับเดียวเท่านั้น คุณสามารถลองใช้วิธี deep_dup จาก ActiveSupport แทนได้
สรุป
คุณได้เรียนรู้เกี่ยวกับการโคลนวัตถุใน Ruby แล้ว! รวมความแตกต่างระหว่างวิธีการคัดลอก &โคลน และการคัดลอกแบบตื้นและแบบลึก
ขอบคุณสำหรับการอ่าน!