考虑这个简单的代码:
class Yeah
attr_reader :foo
attr_reader :fool
attr_reader :feel
def initialize(foo: "test", fool: {}, feel: [])
@foo = foo
@fool = fool
end
end
test = Yeah::new
pp test
test.fool[:one] = 10
pp test
输出:
#<Yeah:0x000008019a84a0 @foo="test", @fool={}>
#<Yeah:0x000008019a84a0 @foo="test", @fool={:one=>10}>
我的问题是,有一种“简单”,“干净”的方式,对真正的只读数组,Hash attributs进行读取加速,或者我需要继承具有很多难以编写的锁定的数组或哈希,(undef,别名)或使用代理,委托或其他类似的模式?
答案 0 :(得分:2)
您可以想到以下内容:
class Yeah
def self.reader_meth
%i(foo fool feel).each do |m|
define_method(m){instance_variable_get("@#{m}").dup.freeze}
end
end
def initialize(foo: "test", fool: {}, feel: [])
@foo = foo
@fool = fool
@feel =feel
end
reader_meth
end
test = Yeah.new
test # => #<Yeah:0x8975498 @foo="test", @fool={}, @feel=[]>
test.fool[:one] = 10 # can't modify frozen Hash (RuntimeError)
test # => #<Yeah:0x8975498 @foo="test", @fool={}, @feel=[]>
答案 1 :(得分:1)
因为我想概括这个解决方案并防止“邪恶”的逃避:
我终于从Arup解决方案到达了这个:
class Module
def attr_readonly *syms
syms.each do |method|
define_method(method){
return self.instance_variable_get("@#{method.to_s}").dup.freeze
}
end
end
end
class Yeah
attr_reader :foo
attr_readonly :fool
attr_reader :feel
def initialize(foo: "test", fool: {}, feel: [])
@foo = foo
@fool = fool
@feel = feel
end
end
答案 2 :(得分:0)
class Yeah
def fool
@fool.freeze
end
def initialize(fool={})
@fool = fool
end
end