Ruby类方法的dup与clone方法疑问:为何User.dup复制了单例方法
关于Ruby中
User.dup复制类方法的解惑 这个问题的核心其实是普通对象的dup和类对象的dup行为不一样——Ruby的Class类特意重写了dup方法,让它的表现和普通对象的dup有明显区别,这才导致了你觉得矛盾的地方。
我来拆解一下:
先回顾普通对象的dup vs clone
对于普通的Ruby对象(比如字符串、自定义实例),dup和clone的差异确实像你了解的那样:
dup只会复制对象的实例方法和当前状态,不会复制它的单例方法(也就是定义在对象 eigenclass 里的方法)clone会完整复制对象的所有内容,包括单例方法
举个直观的例子:
# 创建一个普通对象 obj = Object.new # 给它加一个单例方法 def obj.my_singleton; "I'm a singleton method"; end # 用dup复制 obj_dup = obj.dup obj_dup.my_singleton # 直接报错:NoMethodError(因为dup没复制单例方法) # 用clone复制 obj_clone = obj.clone obj_clone.my_singleton # => "I'm a singleton method"(clone复制了单例方法)
类对象的dup是特殊的!
在Ruby里,类本身就是Class类的实例——比如User这个类,本质上是Class.new创建出来的一个实例。而Class类重写了dup方法,让它的行为更接近clone:
当你调用User.dup时,它会复制原类的所有核心内容,包括:
- 类的名称(你之后可以修改)
- 继承关系链
- 所有实例方法
- 所有单例方法(也就是我们常说的「类方法」)
所以你测试时会发现User.dup能调用active方法,这完全是因为Class#dup的设计就是要复制类方法。
再举个类的例子验证:
class User def self.active; "Return active users"; end end # 复制User类 UserCopy = User.dup # 调用类方法,成功执行 UserCopy.active # => "Return active users"
那类的dup和clone还有区别吗?
有的,但不在类方法的复制上:
clone会保留原类的冻结状态和taint标记,如果原类是冻结的,复制出来的类也是冻结的;dup不会保留这些状态。- 除此之外,两者都会复制类的实例方法、类方法(单例方法)等核心内容。
总结一下
- 普通对象:
dup不复制单例方法,clone复制 - 类对象(Class的实例):
dup和clone都会复制单例方法(类方法),差异仅在冻结/taint状态的保留上
内容的提问来源于stack exchange,提问作者peeyush singla
相关产品推荐
相关产品推荐

