今天写了这么一段代码,发现只要类定义过的 cattr_accessor 的任意一个发生改变,所有都变了
后面翻了cattr_accessor
源码,发现是真的坑,在send("#{sym}=", sym_default_value)
这个地方,并没有对原对象进行拷贝,导致所有的默认值是同一个对象....
<<
方法其实是对最初的对象Array.new
进行操作....
class module
def mattr_accessor(*syms, instance_reader: true, instance_writer: true, instance_accessor: true, default: nil, &blk)
mattr_reader(*syms, instance_reader: instance_reader, instance_accessor: instance_accessor, default: default, &blk)
mattr_writer(*syms, instance_writer: instance_writer, instance_accessor: instance_accessor, default: default)
end
alias :cattr_accessor :mattr_accessor
def mattr_writer(*syms, instance_writer: true, instance_accessor: true, default: nil)
syms.each do |sym|
raise NameError.new("invalid attribute name: #{sym}") unless /\A[_A-Za-z]\w*\z/.match?(sym)
class_eval(<<-EOS, __FILE__, __LINE__ + 1)
@@#{sym} = nil unless defined? @@#{sym}
def self.#{sym}=(obj)
@@#{sym} = obj
end
EOS
if instance_writer && instance_accessor
class_eval(<<-EOS, __FILE__, __LINE__ + 1)
def #{sym}=(obj)
@@#{sym} = obj
end
EOS
end
sym_default_value = (block_given? && default.nil?) ? yield : default
send("#{sym}=", sym_default_value) unless sym_default_value.nil?
end
end
alias :cattr_writer :mattr_writer
end