2

我是 ruby​​ 的新手,一般来说也是编程的新手。我在独立的 ruby​​ 脚本中有一段代码,它从 yaml 文件中读取数据并将该数据分配给方法中的变量。这都是在一个方法中完成的。在方法的定义之外,我调用该方法并打印分配的变量的值。但是,呃,在方法中赋值的变量的值是nil……为什么?这与我假设的面向对象编程有关。有人可以详细说明吗?

下面是代码。先感谢您。

#!/usr/bin/env ruby

require 'pg'
require 'yaml'

source_connection=nil

def load_configurations
    file_name = nil

    ARGV.each do|a|
      file_name = "#{a}"
    end
    dest_options = YAML.load_file(file_name)
    source_connection = dest_options['dest_name']
end

load_configurations()

puts source_connection

#####  returns nothing. why? #####
4

2 回答 2

5

在 Ruby 中,就像在大多数语言中一样(至少我所知道的,Javascript 可能是一个例外),有一个称为可见性范围的概念。

Ruby 中有四个作用域:

  • 全局范围
  • 类范围
  • 方法范围
  • 块范围

它在实践中的含义是为 ex 定义的局部变量。in 方法仅在此方法中可见,除非您明确地向上(使用方法/块调用参数)或向下(使用返回)传递调用堆栈。

在您的情况下,发生的情况是在您分配source_connection给 nil 的方法之外,但是您在不同的范围内引用相同的 var 名称,因此它只分配在那里。Ruby 解决这个问题的方法是定义一个实例变量( @source_connection) 或显式将此变量传递给方法,然后返回它。

专业提示:在 Ruby 中,最后一次评估默认返回,因此您不需要显式编写return source_connection.

编辑:
使用类实例和实例变量,事情会变得更复杂一些,所以如果我只是向您指出元编程 Ruby 书籍的方向,它完美地列出了这些主题,那么最好的办法就是。

EDIT2:
我的重写建议(稍微改变样式 - 对于方法定义,无论是否有参数,总是添加括号是很好的。另一方面,如果没有参数或单个参数,您可以省略 then - 但这取决于根据个人喜好;)我还将缩进更改为 2 个空格 - 我认为它是最常用的。

#!/usr/bin/env ruby

require 'pg'
require 'yaml'

def load_configurations()
  file_name = nil

  ARGV.each do|a|
    file_name = "#{a}"
  end
  dest_options = YAML.load_file(file_name)
  dest_options['dest_name'] # Ruby will return last evaluation
end

source_connection = load_configurations

puts source_connection # now it will print what you expect
于 2013-07-15T17:32:44.820 回答
3

该变量是在方法的范围内创建的,不会设置为在全局范围内定义的变量。有关更多信息,这可能是一个不错的阅读:http ://www.techotopia.com/index.php/Ruby_Variable_Scope

你应该能够做到这一点:

def load_configurations
  file_name = nil

  ARGV.each do |a| 
    file_name = "#{a}"
  end

  dest_options = YAML.load_file(file_name)
  dest_options['dest_name']
end

source_connection = load_configurations
puts source_connection
于 2013-07-15T17:31:28.100 回答