深入探索
冻结对象
通过了解所有这些修改对象的方法,你可能会担心对象有被无意中修改掉的风险。实际上,你可以通过“冻结”它(使用 freeze
方法)来专门固定住对象的状态。一旦冻结,就无法修改对象包含的数据,如果尝试这样做,将抛出 TypeError 异常。然而,在冻结对象时要小心,因为一旦冻结,它就不能“解冻”(unfrozen)。
freeze.rb
s = "Hello"
s << " world"
s.freeze
s << " !!!" # Error: "can't modify frozen string (TypeError)"
你可以使用 frozen?
来专门检查对象是否被冻结:
a = [1,2,3]
a.freeze
if !(a.frozen?) then
a << [4,5,6]
end
请注意,虽然无法修改冻结对象的数据,但可以修改定义它的类。假设你有一个类 X,它包含一个方法 addMethod
,它可以使用给出的符号名称创建新的方法 m
:
cant_freeze.rb
def addMethod( m, &block )
self.class.send( :define_method, m , &block )
end
现在,如果你有一个从 M 类创建的对象 ob
,那么调用 addMethod
来向 M 类添加一个新方法是完全合法的:
ob.freeze
ob.addMethod( :abc ) { puts("This is the abc method") }
当然,如果你想阻止冻结的对象它的所属类,可以使用 frozen?
方法来测试它的状态:
if not( ob.frozen? ) then
ob.addMethod( :def ) { puts("'def' is not a good name for a method") }
end
你也可以冻结类本身(记住,类也是一个对象):
X.freeze
if not( X.frozen? ) then
ob.addMethod( :def ) { puts("'def' is not a good name for a method") }
end