gpt4 book ai didi

ruby - 为什么实例变量在 block 内时似乎消失了?

转载 作者:数据小太阳 更新时间:2023-10-29 06:27:40 29 4
gpt4 key购买 nike

原谅我,伙计们。在 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

尽管 @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

我猜这种(对我来说)奇怪的行为一定与我在一个街区内有关;但真的,我不知道。有人可以启发我吗?

最佳答案

首先,@user 在 Ruby 中不是“私有(private)变量”;这是一个 instance variable 。实例变量在当前对象的范围内可用(self 指的是什么)。我已经编辑了您的问题标题以更准确地反射(reflect)您的问题。

block 就像一个函数,一组要在以后执行的代码。通常该 block 将在定义该 block 的范围中执行,但也可以在另一个上下文中评估该 block :

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

因此,要么您在设置 @user 的范围之外定义 block ,要么 client.request 的实现导致 block 在另一个范围内被评估稍后的。你可以通过写作找到:

client.request("createSession"){ p [self.class,self] }

深入了解 block 中的当前 self 是什么类型的对象。

它们在您的案例中“消失”(而不是抛出错误)的原因是 Ruby 允许您请求任何实例变量的值,即使从未为当前对象设置该值。如果该变量从未被设置,您将返回 nil(如果您启用了它们,则会收到警告):

$ ruby -e "p @foo"
nil

$ ruby -we "p @foo"
-e:1: warning: instance variable @foo not initialized
nil

如您所见, block 也是 closures 。这意味着当它们运行时,它们可以访问定义在与 block 定义相同范围内的局部变量。这就是您的第二组代码按预期工作的原因。闭包是锁定一个值供以后使用的一种极好的方法,例如在回调中。

继续上面的代码示例,您可以看到无论 block 被评估的范围如何,局部变量都可用,并且优先于该范围内的同名方法(除非您提供显式接收器):

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

关于ruby - 为什么实例变量在 block 内时似乎消失了?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6750394/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com