Object#freeze
Object#freezeで、インスタンスの変更(インスタンス変数の変更)を禁止できます。
class Kitten def name @name end def name=(name) @name = name end end mii = Kitten.new mii.name = "mii" #凍結。 mii.freeze #凍結後はインスタンス変数を変更できない。 mii.name = "mii"
実行結果です。
test.rb:7:in `name=': can't modify frozen object (TypeError) from test.rb:17
↓のように明示的にチェックしないとだめなのかと思っていたらそんなことはなかった。ふむ。
... def name=(name) raise "frozen." if frozen? @name = name end ...
ちなみに、Object#freezeでは、インスタンスの再帰的な凍結はされないので注意。以下のような場合、Delegateのインスタンスは凍結されますが、Delegateのインスタンス変数「@delegate」は凍結されません。
class Delegate def initialize( delegate ) @delegate = delegate end def method_missing(name, *args) @delegate.__send__( name, *args ) end attr :delegate, true end mii = Delegate.new( Kitten.new ) mii.name = "mii" #凍結。 mii.freeze #Delegateのインスタンスは凍結されるが、 #Delegateのインスタンス変数「@delegate」は凍結されないため、変更が可能。 mii.name = "mii"