对象、变量和常量

对象、变量和常量


  • https://www.kancloud.cn/imxieke/ruby-base/107291


对象

在 Ruby 中,表现数据的基本单位称为对象(object)。

对象的类型非常多,我们这里只介绍一些常用的对象。

  • 数值对象

    1、-10、3.1415 等是表示数字的对象,另外还有表示矩阵、复数、素数、公式的对象。

  • 字符串对象

    你好、"hello" 等表示文字的对象。

  • 数组对象、散列对象

    表示多个数据的集合的对象。

  • 正则表达式对象

    表示匹配模式的对象。

  • 时间对象

    比如“2013 年 5 月 30 日早上 9 点”等表示时间的对象。

  • 文件对象

    一般我们可以理解为表示文件本身的对象,但确切来说,它是对文件进行读写操作的对象。

  • 符号对象

    表示用于识别方法等名称的标签的对象。

    除此以外,Ruby 还有范围对象(Range)、异常对象(Exception)等。

Ruby 的类(class)表示的就是对象的种类。

对象拥有什么特性等,这些都是由类来决定的。

对象 | 类

  •       |   -

数值 | Numeric 字符串 | String 数组 | Array 散列 | Hash 正则表达式 | Regexp 文件 | File 符号 | Symbol

×× 类的对象”,我们一般也会说成“×× 类的实例(Instance)”。所有 Ruby 对象其实都是某个类的实例,因此在 Ruby 中的对象和实例的意义几乎是一样的。

另外,我们在强调某个对象是属于某个类时,经常会使用“实例”来代替“对象”。例如,我们会说“字符串对象 "foo" 是 String 类的实例”。

变量

Ruby 中有四种类型的变量。

  1. 局部变量(local variable)

  2. 全局变量(global variable)

  3. 实例变量(instance variable)

  4. 类变量(class variable)

变量的命名方式决定了变量的种类。

  • 局部变量

    以英文字母或者 _ 开头。

  • 全局变量

    以 $ 开头。

  • 实例变量

    以 @ 开头。

  • 类变量

    以 @@ 开头。

除了以上四种类型以外,还有一种名为伪变量(pseudo variable)的特殊变量。伪变量是 Ruby 预先定义好的代表某特定值的特殊变量,因此即使我们在程序里给伪变量赋值,它的值也不会改变。Ruby 中,nil、true、false、self 等都是伪变量。它们表面上虽然看着像变量,但实际的行为又与变量有差别,因此称为伪变量。

还有一种叫预定义变量(Pre-defined Variable)的特殊变量。

局部变量与全局变量

首先让我了解一下什么是局部变量。

所谓局部,即变量在程序中的有效范围(也称为变量的作用域)是局部的。也就是说,在程序某个地方声明的变量名,在其他地方也可以使用,程序会也会认为这两个变量是没有关系的。

局部变量也可称为本地变量。

与局部变量相对的是全局变量。只要全局变量的名称相同,不管变量在程序的哪个部分使用,程序就认为是它们是同一个变量。

举个例子,假设有个程序引用了其他程序作为自己的程序一部分。这时,如果原程序与被引用程序中,都有一个相同名称的变量 x,由于 x 是局部变量,因此程序不会认为这两个变量 x 是同一个变量。但是,如果是拥有相同名称的全局变量 $x,则程序会认为这两个变量 $x 是相同的变量。

scopetest.rb

$x = 0
x = 0

require "./sub"

p $x   #=> 1
p x    #=> 0

sub.rb

$x = 1  ## 对全局变量赋值
x = 1   ## 对局部变量赋值

在 scopetest.rb 中,我们预先将变量 $x 和 x 都定义为 0 后,读取 sub.rb 的内容。在 sub.rb 中,我们再把刚才两个变量的值都设为 1。然后,回到 scopetest.rb 程序的第 6 行和第 7 行,我们输出这两个变量的值后会发现,x 的值没有变化,但 $x 的值已经是 1 了。这是由于在 scopetest.rb 以及 sub.rb 中,程序会把 $x 当作同一个变量来处理,而把 x 当作不同的变量来处理。

一般我们并不推荐使用全局变量。全局变量的值在程序的任何地方都可以修改,因此在规模较大的程序中使用时,会增加程序不必要的复杂度,给阅读程序、修改程序造成意想不到的麻烦。本书也很少对全局变量进行说明,示例中也没使用过。

程序首次给局部变量赋值的同时,该局部变量就被初始化了。如果引用了未初始化的局部变量,程序会抛出异常。

> irb --simple-prompt
>> x + 1
NameError: undefined local variable or method ` 1' for main:Object
    from (irb):1
    from /usr/local/bin/irb:16:in `<main>'

实例变量与类变量,是在定义类的时候用到的变量

常量

与变量类似的有常量(constant)。常量的作用和变量一样,是某个对象的“名片”。不过与变量不同的是,对已经赋值的常量再进行赋值时,Ruby 会做出警告。

> irb --simple-prompt
>> TEST = 1
=> 1
>> TEST = 2
(irb):4: warning: already initialized constant TEST
(irb):3: warning: previous definition of TEST was here
=> 2

常量以大写英文字母开头。例如,Ruby 的运行版本(RUBY_VERSION)、运行平台(RUBY_PLATFORM)、命令行参数数组(ARGV)等,都是 Ruby 预定义的好的常量.

保留字

在程序里,如果不小心使用了 end、next 等作为变量名,Ruby 会提示我们语法错误。这些受到限制的单词,我们称为保留字。

> irb --simple-prompt
>>  end = 1
SyntaxError: (irb):8: syntax error, unexpected keyword_end
end = 1
   ^
         from /usr/local/bin/irb:16:in `<main>'

多重赋值

我们已经介绍过“变量=值”这样的变量赋值方法,Ruby 还提供了一个只用一个表达式就能给多个变量赋值的简便方法——多重赋值。很多情况下我们都会用到多重赋值,在这里举几个比较典型的例子供大家参考。

合并执行多个赋值操作

有时我们希望把一组的变量同时赋值。

a = 1
b = 2
c = 3

像这样的赋值语句,程序可以简化为只有一行。

a, b, c = 1, 2, 3

这样就能轻松地将 1、2、3 分别赋值给变量 a、b、c。如果对一组不相关的变量进行多重赋值,程序会变得难懂,因此建议对彼此相关变量进行多重赋值。

即使= 左右两边列表的数量不相等,Ruby 也不会报错。左边被赋值的变量的个数比较多时,Ruby 会自动将 nil 赋值给未分配值的变量。

a, b, c, d = 1, 2
p [a, b, c]    #=> [1, 2, nil]

变量部分比较少时,Ruby 会忽略掉该值,不会分配多余的值。

a, b, c = 1, 2, 3, 4
p [a, b, c]    #=> [1, 2, 3]

变量前加上 *,表示 Ruby 会将未分配的值封装为数组赋值给该变量。

a, b, *c = 1, 2, 3, 4, 5
p [a, b, c]    #=> [1, 2, [3, 4, 5]]
a, * b, c = 1, 2, 3, 4, 5
p [a, b, c]    #-> [1, [2, 3, 4], 5]

置换变量的值

现在我们来考虑一下如何置换变量 ab 的值。通常,我们需要一个临时变量 tmp 暂时地保存变量的值。

a, b = 0, 1
tmp = a    # 暂时保存变量a 的值
a = b      # 将变量b 的值赋值给a
b = tmp    # 将原本变量a 的值赋值给变量b
p [a, b]   #=> [1, 0]

使用多重赋值,只需一行程序就搞定了。

a, b = 0, 1
a, b = b, a    # 置换变量a、b 的值
p [a, b]       #=> [1, 0

获取数组的元素

用数组赋值,左边有多个变量时,Ruby 会自动获取数组的元素进行多重赋值。

ary = [1, 2]
a, b = ary
p a        #=> 1
p b        #=> 2

只是希望获取数组开头的元素时,可以按照以下示例那样做。左边的变量列表以,结束,给人一种“是不是还没写完?”的感觉,建议尽量少用这样的写法。

ary = [1, 2]
a, = ary
p a        #=> 1

获取嵌套数组的元素

我们来看看数组 [1, [2, 3], 4],用之前介绍的方法,我们可以分别取出 1[2, 3]4 的值。

ary = [1, [2, 3], 4]
a, b, c = ary
p a    #=> 1
p b    #=> [2, 3]
p c    #=> 4

像下面那样把左边的变量括起来后,就可以再进一步将内部数组的元素值取出来。

ary = [1, [2, 3], 4]
a, (b1, b2), c = ary    # 对与数组结构相对应的变量赋值
p a    #=> 1
p b1   #=> 2
p b2   #=> 3
p c    #=> 4

只要等号左边的变量的结构与数组的结构一致,即使再复杂的结构,多重赋值都可以轻松对应。

变量的命名方法

以变量名开头来决定变量的种类,这是 Ruby 中对变量命名时唯一要坚决遵守的规则。虽然如此,但是根据以往的编程经验,也有一些非强制性的、约定俗成的变量命名规则。在大多数情况下,遵循这些规则能使程序变得易于阅读,对我们来说有百利而无一害。

不要过多使用省略的名称

有些编程语言会限制变量名的长度,但 Ruby 不需要在意变量名的长度。当然,过长的名称是不便于阅读的,但是与其起个不知所云的短的名称,老老实实地为变量取个长点的好理解的名称,对以后阅读、理解程序是非常有帮助的。

但是,我们也还是有一些约定俗成的短名称变量。进行数学、物理等计算时,根据计算对象的不同,很多情况下会使用短名称的变量名,像坐标使用 xyz,速度使用 vw,循环次数使用 mn 等。另外,我们编写程序时,也经常使用 ijk 等作为循环时需用到的变量名。

对于多个单词组合的变量名,使用 _ 隔开各个单词,或者单词以大写字母开头

也就是说,要么这样叫做 sort_list_by_name,要么叫做 sortListByName。一般来讲,Ruby 中的变量名和方法名使用前者,类名和模块名的使用后者。