我正在阅读Eloquent Ruby书(到目前为止很棒的书)并且不理解一个讨论集团,参数和范围的部分。这是代码......
class SomeApplication
# Rest of the class omitted...
def do_something
with_logging('load', nil) { @doc = Document.load( 'book' ) }
# Do something with the document...
with_logging('save', @doc) { |the_object| the_object.save }
end
def with_logging(description, the_object)
begin
@logger.debug( "Starting #{description}" )
yield( the_object )
@logger.debug( "Completed #{description}" )
rescue
@logger.error( "#{description} failed!!")
raise
end
end
end
这本书说代码比它需要的更复杂,因为@doc在代码块中自动可见。因此,没有必要将其作为论据传递下去。
我不明白他在谈论哪个参数,@ doc或|the_object|
。在更改它以消除不必要的复杂性后,此代码会是什么样的?
或者是否意味着在with_logging('load', nil)
中创建的@doc仍然是可见的?即使是这种情况,我也不确定底部的with_logging
方法如何访问它。
答案 0 :(得分:1)
块(和lambdas / procs)是闭包。这意味着他们可以访问创建它们的环境中的任何变量。@doc
是一个实例变量,因此它始终在类的上下文中。 @doc
是绑定到the_object
的值,这是不必要的。修改后的代码如下:
class SomeApplication
# Rest of the class omitted...
def do_something
with_logging('load') { @doc = Document.load( 'book' ) }
# Do something with the document...
with_logging('save') { @doc.save }
end
def with_logging(description)
begin
@logger.debug( "Starting #{description}" )
yield
@logger.debug( "Completed #{description}" )
rescue
@logger.error( "#{description} failed!!")
raise
end
end
end
答案 1 :(得分:1)
@doc
是instance variable。它在对象的范围内定义(在本例中为类SomeApplication
的实例),通常用于存储“属于”实例的值。实例变量始终可用于对象的实例方法。它们在对象外部不可用,除非您将它们变为属性。
您的困惑:该示例可能源于作者将方法do_something
中的值传递给方法with_logging
的迂回方式。调用with_logging
时,会收到两个参数'save'
和@doc
。在with_logging
中,局部变量description
设置为'save'
,局部变量the_object
设置为@doc
。然后使用参数yield
调用the_object
,这将the_object
传递给第二次调用with_logging
中定义的代码块,您可以将其视为一种匿名函数。但是,正如作者所指出的那样,@doc
已经在with_logging
的第一次调用中设置了,因此没有必要将其作为参数传递。他本可以写第二个函数调用:
with_logging('save') { @doc.save }
和第一个:
with_logging('load') { @doc = Document.load('book') }
然后在没有参数的情况下调用yield
,效果会相同。
答案 2 :(得分:0)
它是一个实例变量(由@表示)所以在整个类中都可以使用任何方法。