我在理解Ruby中变量和符号的语法时遇到了一些麻烦。我正在阅读一本名为Agile Web Development with Rails 4的书。我正在尝试学习Ruby和Rails,以便我可以构建网站。
我读过的书籍和教程有时会在它们前面加上带有“@”符号的变量,然后一些变量在它们前面没有@符号。他们之间有什么区别?
另外,我对结肠感到困惑。有时我看到冒号位于前面的变量,例如:order,然后我看到冒号末尾的变量,例如冒号:我不明白冒号在做什么。
请帮助我理解Ruby语法。
答案 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
)内访问它们所在的位置定义