了解Ruby变量和符号?

时间:2013-11-04 15:19:36

标签: ruby-on-rails ruby syntax

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

我读过的书籍和教程有时会在它们前面加上带有“@”符号的变量,然后一些变量在它们前面没有@符号。他们之间有什么区别?

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

请帮助我理解Ruby语法。

4 个答案:

答案 0 :(得分:8)

@开头的变量是实例变量,其他语言中的“属性”。 “经典”变量是其方法/块范围的本地变量,而实例变量是对象的特定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

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

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

更新,因为ruby 2.2符号可能在某些情况下被垃圾收集(当没有保留参考且不需要进行比较时)

答案 1 :(得分:3)

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

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

答案 2 :(得分:2)

  

有时会在它们前面加上带有“@”符号的变量,然后有些变量在它们前面没有@符号。

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

  

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

他们被称为symbols

  

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

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

也按照您的要求阅读:

答案 3 :(得分:1)

实例变量:@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)内访问它们所在的位置定义