有一個辦法的事實 - 哈克(但有趣)這種方式並不意味着生產(並且相對較慢)。我的示例實現僅適用於單個對象,但可以擴展爲支持許多對象。
假設如下設置:
class Foo
def initialize
@a = :foo
end
def set_b; @b = 3; end
def set_c; @c = 7; end
end
def freeze_variables_of(obj)
frozen_variables = obj.instance_variables
set_trace_func lambda {|event, file, line, id, binding, classname|
if classname == obj.class
this = binding.eval 'self'
if this == obj
(this.instance_variables - frozen_variables).each {|var| this.remove_instance_variable var}
end
end
}
end
隨着使用set_trace_func
我們可以設置一個被稱爲very often(每條語句通常超過一次)PROC。在Proc中,我們可以檢查實例變量並刪除不需要的變量。
讓我們來看一個例子:
a = Foo.new
# => #<Foo:0x007f6f9db75cc8 @a=:foo>
a.set_b; a
# => #<Foo:0x007f6f9db75cc8 @a=:foo, @b=3>
freeze_variables_of a
a.set_c; a
# => #<Foo:0x007f6f9db75cc8 @a=:foo, @b=3>
我們看到,後做事「凍結」,set_c
無法設置實例變量(實際上變量在非常時刻取出set_c
方法返回)。
與凍結對象(使用a.freeze
)(我推薦用於任何真實世界的應用程序)相反,這種方式允許您修改所有允許的實例變量,同時禁止新的實例變量。
如果你直接分配實例變量(儘管Alex的方法可能更快,但依賴於存取方法),這甚至可以工作。
這應該很容易:http://m.onkey.org/ruby-i-don-t-like-3-object-freeze –
這不僅僅是防止意外創建其他實例變量。 – Max
我不認爲這會很有幫助。例如:'p t.instance_variable_set:@a,7#=> RuntimeError:無法修改凍結的Test' –