str = "hello" frozen_str = str.freeze copy_dup = frozen_str.dup copy_clone = frozen_str.clone puts copy_dup.frozen? puts copy_clone.frozen?
In Ruby, dup creates a shallow copy but does not copy the frozen state of the original object. clone, however, copies the frozen state as well. So copy_dup.frozen? returns false while copy_clone.frozen? returns true.
obj = Object.new def obj.greet; "hello"; end obj_dup = obj.dup obj_clone = obj.clone puts obj_dup.respond_to?(:greet) puts obj_clone.respond_to?(:greet)
Singleton methods belong to a single object. When you use dup, singleton methods are not copied. When you use clone, singleton methods are copied. So obj_dup does not respond to greet, but obj_clone does.
class Person attr_accessor :name, :address end person1 = Person.new person1.name = "Alice" person1.address = { city: "NY" } person2 = person1.dup person2.address[:city] = "LA" puts person1.address[:city]
The dup method creates a shallow copy of the object. This means that the top-level object is copied, but nested objects like the address hash are not duplicated; both objects share the same nested hash. So modifying the nested hash in person2 affects person1 as well.
Cloning a frozen String does not raise an error, but cloning a frozen Object raises a RuntimeError. Duping a frozen object does not raise an error in either case. So option A raises an error.
Using Marshal.load(Marshal.dump(obj)) serializes the object and then deserializes it, creating a deep copy including nested mutable objects. Both dup and clone create shallow copies, so nested objects remain shared. Freezing prevents modification but does not copy.