Trong Ruby #dup và #clone đều tạo ra các shallow copies. Vậy thì lúc nào nên dùng #dup lúc nào nên dùng #clone.
#clone copy cả trạng thái frozen còn #dup thì không
Ví dụ:
class Animal end a = Animal.new a.freeze a.clone.frozen? #=> true a.dup.frozen? #=> false
Như có thể thấy trong ví dụ trên, object #clone vẫn duy trì trạng thái frozen của object gốc còn object #dup thì không
khi update các thuộc tính của object #clone và object #dup
Ví dụ:
user_clone = User.first.clone #=> #<User id: 1, name: "user 01", email: nil, created_at: "2018-12-27 07:26:28", updated_at: "2018-12-27 07:26:28"> user_dup = User.first.dup #=> #<User id: nil, name: "user 01", email: nil, created_at: nil, updated_at: nil>
Trong ví dụ trên, #clone object chia sẻ toàn bộ các thuộc tính của object gốc còn #dup object được coi như một bản ghi mới và nó chỉ chia sẻ các liên kết trong object gốc. Điều đó có nghĩa là nếu chúng ta thay đổi thuộc của #clone object thì sẽ thay đổi thuộc tính của object gốc còn #dup object sẽ tạo ra một bản ghi mới hoàn toàn độc lập.
Với #clone:
u = User.first #=> #<User id: 1, name: "user 01", email: nil, created_at: "2018-12-27 07:26:28", updated_at: "2018-12-27 07:26:28"> u.clone.update_attribute(name: "new user") #=> UPDATE `users` SET `name` = 'new user', `updated_at` = '2019-01-18 07:31:39' WHERE `users`.`id` = 1 u.name #=> "new user"
Với #dup:
u = User.first #=> #<User id: 1, name: "user 01", email: nil, created_at: "2018-12-27 07:26:28", updated_at: "2018-12-27 07:26:28"> u.dup.update_attribute(name: "new user") #=> INSERT INTO `users` (`name`, `email`, `created_at`, `updated_at`) VALUES ('new user', nil, '8gkHg+VRPaWJMzsFDH3RIYK6Ffg=', '2019-01-18 07:36:22', '2019-01-18 07:36:22', TRUE) u.name #=> "user 01" User.last.name #=> "new user"
singleton method
#clone object có khả năng copy singleton methods của object gốc còn #dup object thì không thể. Ví dụ:
class Dog def bark "woff woff" end end dog1 = Dog.clone dog1.bark #=> "woff woff" dog2 = Dog.dup dog2.bark #=> NoMethodError
Tổng kết
Nói chung, #clone và #dup có ngữ nghĩa khác nhau trong các lớp con cháu. Trong khi #clone được sử dụng để sao chép một đối tượng, bao gồm cả trạng thái, method bên trong của nó, #dup thường sử dụng lớp của đối tượng con cháu để tạo ra bản ghi mới.
Thanh for reading and happy coding!