English 中文(简体)
为什么我不能在Ruby的方法中 访问本地变量?
原标题:Why can t I access a local variable inside a method in Ruby?
  • 时间:2012-05-28 03:53:54
  •  标签:
  • ruby

我有鲁比文件叫测试 rb

ff="ff"
def test
  puts ff
end

我执行它,有错误:

test.rb: 3: in` test: 未定义本地变量或方法'ff for main: object (名称错误)

原因是什么?有文件可以解释吗?

最佳回答

test 方法定义中, test 方法定义中无法进入 test 方法的原因很简单,就是方法(以 def 关键词创建的)创造了新的范围。与分别使用 class module 关键词定义类别和模块相同。

main(顶层物体)的作用与这种情况的范围问题几乎完全无关。

请注意,如果您想要您的 test 方法能够访问定义上下文定义的本地人,请使用 define_method (或者在您的情况下使用 define_singleton_method 方法),请在此查阅:

ff = "hi"
define_singleton_method("test") { ff }
test #=> "hi"

def 关键词不同的是, define_method 方法组不创建新范围,而是关闭当前范围,捕捉任何本地变量。

使用 的理由不是 main 在某种程度上是一个“特例”,而是顶层定义的ivar 是 main 的一等, 因而可以进入 main 上引用的方法。

然而, test 方法与 main 有何关系?这不是一种方法 on just on main 本身----实际上是一种在 Object 类中定义的私人实例方法。这意味着 test 方法(作为一种私人方法)将几乎可用到您的红宝石方案中的每一个对象。在顶层定义的所有方法( main )实际上都定义为 Object 类中的私人实例方法。

有关Ruby最高层的更多信息,见此文章:http://banisterfiend.wordpress.com/2010/11/23/what-is-the-ruby-top-level/

问题回答

Ruby的范围既简单又复杂。

首先,你必须记住,一切都是物体,一切都有一个范围。

要直接回答您的问题, main 是一个对象, 当您写入 def x... 时, 您会重新定义对象上的方法 main

年/年观察温度:

# note the error describes 
[1] pry(main)> main  main:Object 
NameError: undefined local variable or method  main  for main:Object
from (pry):1:in  <main> 

# self is the current object, which is main
[2] pry(main)> self
=> main 

# note main is an object of type Object
[3] pry(main)> self.class
=> Object 

# main has methods
[4] pry(main)> self.methods
=> [:to_s, :public, etc etc]

所以当你写作时

ff = "ff"
def test
    puts ff
end

你真正真正要做的是

class main
    ff = "ff"
    def test
        puts ff
    end
end

无效, 因为 ff 已经超出范围。 要解决这个问题, 您必须将 < code> ff 转换为实例变量, 所以将其名称以 < code @ /code > 预设 。 以下将有效 :

@ff = "ff"
def test
    puts @ff
end

test

请注意,对于main 来说,这似乎比普通类(见下文)要特殊。

如果我们有自己的测试课:

class Test1
    ff = "ff"
    def test
        puts ff
    end
end

Test1.new.test # undefined variable/method  ff  error

这失败的原因是 ff 没有按照预期的正确范围定义。 而是覆盖到采集器执行我们分类声明的时间 。

让我们试一下上面的修补方法:

class Test1Fixed
    @ff = "ff"
    def test
        puts @ff
    end
end

Test1Fixed.new.test # results in blank line

这很奇怪。

让我们添加此方法 :

def ff?
    puts "ff is: #{@ff.nil? ? "nil" : "not nill"}"
end

Test1Fixed.new.ff? # => ff is: nil

为什么是@ff零?

以下可以更明确地说明这一点:

class Test2
    puts "Where am i?"
    @instance = "instance"

    def initialize
        puts "Initalize"
    end

    puts "pants on"

    def test
        puts "This will NOT output  instance : #{@instance}"
    end

    def self.class_test
        puts "This WILL output  instance : #{@instance}"
    end
end

puts "Creating new Test2 Object"
t = Test2.new
puts "Calling test on Test2 Object"
t.test

puts "Calling class_test on Test2 Class object" 
Test2.class_test

运行中我们得到以下输出 :

$ ruby scope.rb 
Where am i?
pants on
Creating new Test2 Object
Initalize
Calling test on Test2 Object
This will NOT output  instance : 
Calling class_test on Test2 Class object
This WILL output  instance : instance

如您所见, 内插器按顺序运行于我们的类声明, 就像其它任何地方一样, 并输出我们的 < code> puts 语句。 当我们开始调用方法时, 这会更有趣 。 写入 < code\\ intance =... < / code > 和写入 < code > self. instance =... < / code > 相同, 所以您能猜出我们定义的实例在哪里吗? 是的, 在 测试2 类对象上( 不是测试2 对象 ) 。

这就是为什么当我们调用 test > 时,没有输出任何内容,因为在 test , self 中, 指向无线 test2 对象,而不是 test2 类对象 (这是我们设置@ intance to be anything! > 。 这就是为什么你在 初始化 中设置实例变量, 在那里, self 指向实际对象。

当我们通过 self. class_ test 来定义类方法,然后在测试2 类对象( Test2. class_ test )上调用该方法时,你可以看到我们得到预期输出, 因为在此范围内定义了

希望这能说得通

< a href=> "http://rubykoans.com/" rel="noreferrer" > http://rubykoans.com/ 范围部分可能有助于巩固其中一些知识。

在 Ruby 中, 没有 sigil 的名称总是有“ 本地” 范围 。 Ruby 使用词汇范围, 所以在方法中, 名称总是只指该方法 。

The other scopes are global, instance and class. Here is a good document about them: http://en.wikibooks.org/wiki/Ruby_Programming/Syntax/Operators#Scope

解决你的问题有几种方法; 我最喜欢的就是通过打印的东西作为论据:

ff = "ff"
def test(ff)
  puts ff
end

更有可能的是,您会包装您在课堂上做的事情, 并使用实例变量 。

你也可以只使用一个全球变量($ff),但这样疯狂的谎言。

为什么我不能在Ruby的方法中 访问本地变量?

因为它是一个 < em> 本地变量 < / em > 。 本地变量在它们定义的范围内是本地的。 这就是为什么它们被称作“ 本地变量 ” 。

在此情况下, 您定义了脚本范围中的一个本地变量, 因此它在脚本范围中可见, 并且 nowhere else





相关问题
Ruby parser in Java

The project I m doing is written in Java and parsers source code files. (Java src up to now). Now I d like to enable parsing Ruby code as well. Therefore I am looking for a parser in Java that parses ...

rails collection_select vs. select

collection_select and select Rails helpers: Which one should I use? I can t see a difference in both ways. Both helpers take a collection and generates options tags inside a select tag. Is there a ...

RubyCAS-Client question: Rails

I ve installed RubyCAS-Client version 2.1.0 as a plugin within a rails app. It s working, but I d like to remove the ?ticket= in the url. Is this possible?

Ordering a hash to xml: Rails

I m building an xml document from a hash. The xml attributes need to be in order. How can this be accomplished? hash.to_xml

multiple ruby extension modules under one directory

Can sources for discrete ruby extension modules live in the same directory, controlled by the same extconf.rb script? Background: I ve a project with two extension modules, foo.so and bar.so which ...

Text Editor for Ruby-on-Rails

guys which text editor is good for Rubyonrails? i m using Windows and i was using E-Texteditor but its not free n its expired now can anyone plese tell me any free texteditor? n which one is best an ...