Object#clone
obj.clone -> obj clone creates a shallow copy of an object. Unlike dup, it also copies the object’s singleton class (methods defined on that specific object) and preserves the frozen status.
Syntax
obj.clone
The method returns the cloned object immediately, without any arguments to configure the copy depth or behavior. Because the signature is so simple, clone is easy to call but also easy to misunderstand — it does not look like it does much, yet preserving the singleton class and freeze status makes it meaningfully different from dup. That difference is why Ruby provides both methods instead of merging them into a single duplicating API with optional flags.
Parameters
clone accepts no parameters.
Examples
Basic usage
original = "hello"
copy = original.clone
original << " world"
puts original # => "hello world"
puts copy # => "hello"
That first example shows the simple case: a cloned string starts with the same content, then diverges when the original changes. It is a good reminder that clone copies the object itself, not the objects referenced inside it. For strings, that often means the copy is easy to reason about, because the state is small and visible.
Preserving freeze status
original = "immutable".freeze
copy_clone = original.clone
# clone preserves frozen status
puts copy_clone.frozen? # => true
Frozen objects are where clone starts to feel different from dup. If code depends on immutability, keeping the frozen flag can matter just as much as copying the visible value. That makes clone safer in places where the copy is expected to behave exactly like the original, including its frozen state.
Cloning with singleton methods
obj = Object.new
def obj.greet; "hello"; end
cloned = obj.clone
cloned.respond_to?(:greet) # => true
# dup would not include the greet method
Singleton methods are a niche feature, but they are the reason many Ruby developers reach for clone instead of dup. When behavior lives directly on one object, copying that behavior keeps the duplicate useful without having to rebuild the custom methods by hand. That is especially helpful in small objects with ad hoc behavior.
Cloning an array
original = [1, 2, [3, 4]]
copy = original.clone
original[2] << 5
puts original.inspect # => [1, 2, [3, 4, 5]]
puts copy.inspect # => [1, 2, [3, 4, 5]] - nested array is shared!
Arrays make the shallow-copy behavior easier to see because nested data changes in both places. That is the part people usually miss on a first read: clone does not walk the whole structure and duplicate everything inside it. If you need that level of isolation, the copy step needs to be more deliberate.
Frozen string literals
In Ruby 3.0+, strings from frozen string literals are frozen by default. When you clone a frozen string, the copy remains frozen:
frozen = "frozen".freeze
puts frozen.clone.frozen? # => true (still frozen)
This matters when working with immutable data patterns or performance optimization with frozen strings.
When to use clone
clone is a good fit when you need an object that behaves exactly like the original, including custom singleton methods and frozen state. That makes it useful for decorated objects or one-off helpers that carry behavior along with data. If you only need a plain copy of the data, dup is often enough and can be easier to reason about.
Remember that clone is still a shallow copy. Nested arrays, hashes, and other objects are shared unless you copy them separately, so later mutations can still affect both objects. That distinction matters any time the copied object will be edited in more than one place.
Errors
TypeError— If the object is uncloneable (some special objects like symbols before Ruby 3.0).