【问题标题】:Understanding Ruby variables and symbols?了解 Ruby 变量和符号?
【发布时间】:2013-11-15 06:15:05
【问题描述】:

我在理解 Ruby 中变量和符号的语法时遇到了一些麻烦。我正在阅读一本名为 Agile Web Development with Rails 4 的书。我正在尝试同时学习 Ruby 和 Rails,以便我可以构建网站。

我一直在看的书和教程,有时候变量前面有“@”符号,然后有些变量前面没有@符号。它们有什么区别?

另外,我对冒号感到困惑。有时我看到冒号在前面的变量,例如:order,然后我看到冒号在末尾的变量,例如冒号:。我不明白冒号在做什么。

请帮助我理解 Ruby 语法。

【问题讨论】:

标签: ruby-on-rails ruby syntax


【解决方案1】:

@ 开头的变量是实例变量,在其他语言中是“属性”。而“经典”变量在其方法/块的范围内是本地的,而实例变量对于对象的特定 instance 是本地的,例如:

class Foo

  def initialize(bar)
    @bar = bar
  end

  def bar
    @bar # the variable is specific to this instance
  end

  def buzz
    buzz = 'buzz' # this variable is not accessible outside of this method
  end

end

您还可以看到以@@ 开头的变量,它们是类变量,可以被类的每个实例访问并与子类的每个实例共享。通常不鼓励使用这些变量,主要是因为子类共享变量,这会导致很多混乱。

在 Ruby 中一切都是对象,类是对象(类Class 的实例),所以你也可以拥有类实例变量:

class Foo

  def self.bar
    @bar #we are in class Foo's scope, which is an instance of class Class
  end

  def self.bar=(bar)
    @bar = bar
  end

  def bar
    @bar # Foo.new.bar != Foo.bar 
  end

end

所谓的“带冒号的变量”是不是变量。它们是一种特殊类型的字符串,称为 symbol,它是不可变的,并且针对解释器的快速识别进行了优化,实际上,它们在内部存储为指针,因此 :this == :this 是一个非常快速的操作。

此属性使它们成为哈希键的理想候选者,因为它们提供快速检索或“标志”传递给方法;将它们视为一种“代表”他们所说的松散常数。它们的不变性也很危险:曾经创建的所有符号永远不会被垃圾收集;创建数千个符号很容易造成内存泄漏,因此请明智地使用它们。

更新,因为 ruby​​ 2.2 符号可能在某些情况下会被垃圾收集(当不保留引用且不需要比较时)

【讨论】:

  • 您关于类变量和符号的可怕警告仅适用于粗心使用。在编程中滥用任何东西都会导致问题;滥用符号会导致过多的内存消耗,但普通代码不会有问题,它需要在不寻常的情况下动态创建它们才能导致这种情况。使用类变量需要谨慎,它们的存在通常是变量范围被滥用的危险信号,但它们也使得在对象实例之间干净地共享变量状态成为可能。我们总是必须知道我们在做什么,否则就会发生混乱。
  • 我不知道为什么是-1,但我怀疑是因为我上面评论的。
【解决方案2】:

带有@ 符号的变量是实例变量。这意味着只要声明它们的类的实例持续存在,它们就会持续存在。因此,如果您有一个名为Message 的类,并且每条消息都有一个名为@subject 的变量,那么当您实例化一条新消息时,只要消息对象本身存在,它就会将该主题变量保留在内存中。现在,如果它没有@ 符号,一旦它在“超出范围”中声明的函数又名完成,该变量将“丢失”,因为函数完成并且内存被 Ruby VM 回收。还有以两个@ 符号开头的“类变量”。这意味着该变量在类的所有实例之间共享。

至于冒号,如果它在变量之前意味着它是一个“符号”,它通常用作 Ruby 中哈希和其他数据位的标识符。如果它位于单词的末尾,则意味着它是 Ruby 1.9+ 语法中哈希标识符的关键部分。

【讨论】:

  • 为了完整起见,如果冒号位于单词的末尾,则它是哈希的关键部分并且是一个符号。
【解决方案3】:

实例变量: (@foo = '123') 定义了一个实例变量,并在整个请求的当前实例中保持其值。在 rails mvc 范例中,最常见的实例变量用于帮助将数据从控制器传递到视图,并允许您在控制器的一个部分中定义事物并在另一部分中使用。

class ProjectsController < ApplicationController
  before_filter :find_project

  def show; end

  def update
    if @project.update_attributes(params[:project])
      ...
    end
  end

  private
  def find_project
    @project = Project.find(params[:id])
  end
end

在上面的代码中,您可以看到在每个方法之前运行的 before 过滤器。在上述情况下,我们找到当前项目并将其保存到实例变量中。而且因为它是一个实例方法,所以它可以在这个类中的任何地方访问,也可以访问用于呈现 html 的视图。

局部变量: (foo = '123') 顾名思义,它们只能在定义它们的当前方法 (def) 中访问。 p>

【讨论】:

    【解决方案4】:

    有时变量前面有“@”符号,然后有些变量前面没有@符号。

    带有"@"符号的变量是实例变量,前面没有@,可以是常量,也可以是局部变量,也可以是全局变量。阅读Ruby Programming/Syntax/Variables and Constants

    有时我会看到冒号在前面的变量,例如 :order

    他们被称为symbols

    然后我看到冒号结尾的变量,例如冒号:。我不明白冒号在做什么。

    这些可能是哈希语法(正如您给我们的提示,所以我猜),其中键是符号。示例:{foo: 1} - 这是Hash

    也按您的要求阅读:

    【讨论】:

    • 实例变量、局部变量和全局变量有什么区别?实例变量有什么用?
    • @SameerAnand 你应该花一些时间阅读有关面向对象的理论和变量范围。这些不是特定于 ruby​​ 的概念。
    • 我对面向对象编程了如指掌,我一直在使用 Java。但是,我在迁移到 Ruby on Rails 时遇到了麻烦,因为语法完全不同,Rails 对我来说是全新的东西,而 Web 开发是我在 Java 中从未做过的事情。
    • @SameerAnand 那你就知道什么是实例变量了,局部变量、全局变量、实例变量的区别。大多数 Ruby 编程指南都涵盖了语法和精确语义。在 Rails 中,实例变量也用于将数据传输到视图层。
    猜你喜欢
    • 2013-12-02
    • 2012-08-27
    • 1970-01-01
    • 2011-09-11
    • 1970-01-01
    • 1970-01-01
    • 2017-07-31
    • 1970-01-01
    • 2014-09-16
    相关资源
    最近更新 更多