如果在类中声明但在方法中有效,则无法识别实例var

时间:2018-03-17 15:43:45

标签: ruby scope

我是来自Java背景的Ruby的新手。显然,我还不了解实例方法和变量之间的关系。我刚才有这样的代码:

class Problem022
  FILENAME = "resources/p022_names.txt"
  @name_array = [] # <--- class line 3

  def do_problem
    read_input()
    sort_input()

    # do more stuff
  end

  def read_input
    # <--- read_input line 2

    File.open(FILENAME, "r") do |file|
      file.each_line do |line|
        scanner = StringScanner.new(line)

        while scanner.exist?(/,/) do
          name = scanner.scan_until(/,/)

          @name_array.push(name) # <--- marked line
        end

    # more logic
  end

  def sort_input()
    @name_array.sort!
  end

  # other methods
end

puts problem = Problem022.new.do_problem()

我确认这个工作正常直到“标记线”(见上面的评论),但在那一行,我收到了错误

   in read_input'中的块(2级):nil的未定义方法`push':NilClass(NoMethodError)

我能够通过(有点盲目地)添加线来解决它

@name_array = []

在“read_input line 2”,但我不明白为什么会这样。为什么方法不能识别类体中实例变量@name_array的声明?它似乎能够使用常量FILENAME就好了,并且它在基本相同的地方定义。方法和变量都是实例,而不是类,所以我不希望有任何问题。我刚刚意识到,即使“第3课”的声明被注释掉,该程序仍然运行正常,这只会让我更加困惑。

我在Ruby中读过多个范围定义,但没有一个为我清除这个。我误解了什么?

1 个答案:

答案 0 :(得分:2)

这里有一些代码可以说明“错误”。

class Problem
  @name = 'foo' # this belongs to the class, because that's what current `self` is.

  # instance method
  # inside of this method, `self` will be an instance of the class
  def action
    @name
  end

  # class method (or class instance method)
  # inside of this method, `self` will refer to the class
  def self.action
    @name
  end
end

p1 = Problem.new # an instance of the class
p2 = Problem # the class itself

p1.action # => nil, you never initialize @name in the context of class instance
p2.action # => "foo"

关键点:

  • 类是对象,也可以包含实例变量。这些变量与该类实例的变量无关。
  • “当前自我”的概念是ruby的基本原理之一(与“隐式接收方法调用”相关)。没有理解你就不会走得太远。