rubyguides

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).

See Also