【问题标题】:Instance var not recognized if declared in class but does work in method如果在类中声明但在方法中有效,则无法识别实例 var
【发布时间】:2018-03-17 15:43:45
【问题描述】:

我是来自 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()

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

在 read_input 中的“块(2 级)”中:未定义方法“push”用于 nil:NilClass (NoMethodError)

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

@name_array = []

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

我已经阅读了 Ruby 中的多个范围定义,但没有一个为我解决了这个问题。我误会了什么?

【问题讨论】:

  • 是的,它被问过无数次了。让我给你找一个很好的副本。
  • 我想,但我的搜索技能达不到它。我看过一些帖子,但它们对我没有帮助。
  • 这里,这个应该够近了:stackoverflow.com/questions/25025235/…
  • 看一看。如果好,我会以重复的形式关闭问题
  • 看起来像一个类似的主题,但我看不出它如何回答我关于为什么根本无法识别初始声明的问题......?

标签: ruby scope


【解决方案1】:

这里有一些代码应该可以说明发生了什么“错误”。

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​​ 的基础之一(与“隐式接收器方法调用”有关)。不理解它,你不会走得很远。

【讨论】:

  • IIRC,“当前自我”的概念在名为“metaprogramming ruby​​”的书中得到了很好的解释。但目前可能有点太高级了。
  • 我已经好几年没有阅读初级 ruby​​ 书籍了,也许他们也解释了。 (再想一想,他们必须。)
  • 好的,您的第一个代码内注释很有帮助。我现在收集到,即使 @-vars 被称为“实例变量”,它们也不是类的每个实例都有自己的副本的东西。相反,它们是类的变量,而类本身是超类的实例。与Java的static vars 有点相似(但可能不是直接相似,如果我看得够深的话)?无论如何,我想我知道接下来我需要阅读 Ruby 的 self 和类结构。
  • @SOLO:不过,有一个小修正。 “相反,它们是类的变量” - 不,它们是对象的变量。类是一个对象。该类的实例也是如此。不同的对象,不同的独立变量集。
  • 我可以说“类是 Ruby 中的对象”,但我还没有完全理解这个概念。虽然超出了这个问题的范围。
猜你喜欢
  • 2013-05-16
  • 2020-10-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多