Dan*_*Tao 26 ruby block instance-variables savon
伙计们,请原谅我.对于Ruby来说,我充其量只是一个新手.我只是想知道对我来说看起来很奇怪的行为的解释.
我正在使用Savon库与我的Ruby应用程序中的SOAP服务进行交互.我注意到以下代码(在我编写的用于处理此交互的类中)似乎传递空值,我希望成员字段的值可以去:
create_session_response = client.request "createSession" do
soap.body = {
:user => @user, # This ends up being empty in the SOAP request,
:pass => @pass # as does this.
}
end
Run Code Online (Sandbox Code Playgroud)
尽管这是一个事实,即@user
与@pass
已初始化为非空字符串.
当我更改代码以使用本地代码时,它的工作方式与我期望的一样:
user = @user
pass = @pass
create_session_response = client.request "createSession" do
soap.body = {
:user => user, # Now this has the value I expect in the SOAP request,
:pass => pass # and this does too.
}
end
Run Code Online (Sandbox Code Playgroud)
我猜这个奇怪的(对我来说)行为必须与我在一个街区内的事实有关; 但实际上,我不知道.有人可以在这个上启发我吗?
Phr*_*ogz 36
首先,@user
不是Ruby中的"私有变量"; 它是一个实例变量.实例变量在当前对象的范围内(self
引用的内容)可用.我已编辑了您问题的标题,以便更准确地反映您的问题.
块就像一个函数,一组代码将在以后执行.通常,该块将在定义块的范围内执行,但也可以在另一个上下文中评估块:
class Foo
def initialize( bar )
# Save the value as an instance variable
@bar = bar
end
def unchanged1
yield if block_given? # call the block with its original scope
end
def unchanged2( &block )
block.call # another way to do it
end
def changeself( &block )
# run the block in the scope of self
self.instance_eval &block
end
end
@bar = 17
f = Foo.new( 42 )
f.unchanged1{ p @bar } #=> 17
f.unchanged2{ p @bar } #=> 17
f.changeself{ p @bar } #=> 42
Run Code Online (Sandbox Code Playgroud)
因此,您要么在@user
设置范围之外定义块,要么实现client.request
导致稍后在另一个范围内评估块.你可以写一下:
client.request("createSession"){ p [self.class,self] }
Run Code Online (Sandbox Code Playgroud)
了解self
块中当前对象的类型.
它们在你的情况下"消失"而不是抛出错误的原因是Ruby允许你请求任何实例变量的值,即使从未为当前对象设置了值.如果从未设置过该变量,那么您只需返回nil
(如果启用了它们,则会发出警告):
$ ruby -e "p @foo"
nil
$ ruby -we "p @foo"
-e:1: warning: instance variable @foo not initialized
nil
Run Code Online (Sandbox Code Playgroud)
正如您所发现的,块也是封闭的.这意味着当它们运行时,它们可以访问在定义块的同一范围内定义的局部变量.这就是您的第二组代码按预期工作的原因.闭包是一种很好的方法,可以锁定一个值,以便以后使用,例如在回调中.
继续上面的代码示例,您可以看到局部变量可用,无论评估块的范围如何,并且优先于该范围内的同名方法(除非您提供显式接收器):
class Foo
def x
123
end
end
x = 99
f.changeself{ p x } #=> 99
f.unchanged1{ p x } #=> 99
f.changeself{ p self.x } #=> 123
f.unchanged1{ p self.x } #=> Error: undefined method `x' for main:Object
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
6125 次 |
最近记录: |