# 变量

Ruby 中有四种类型的变量,变量的命名方式决定了变量的类型

  1. 局部变量
    以英文字母或者_开头

  2. 全局变量
    以 $ 符号开头

  3. 实例变量
    以 @ 符号开头

  4. 类变量
    以 @@ 开头

除了上述四种类型以外,还有伪变量预定义变量这两种特殊变量。它们是 Ruby 预先定义好的
代表某特定值的特殊变量。伪变量不能改变其本身的值,对其赋值会产生错误,Ruby 中,self、
true、false、nil 等都是伪变量。预定义变量全部都是以 $ 开头的变量,$$ 就是其中一个,
它的值表示当前执行中的 Ruby 进程 ID

常量:以大写英文字母开头,多个单词间使用下划线 (_) 隔开。比如 Ruby 的运行版本 (RUBY_VERSION)、命令行参数数组 (ARGV) 等,都是 Ruby 预先定义好的常量。对已经赋值的常量再进行赋值时,Ruby 会做出警告

对常量再次赋值
irb(main):001:0> IS_CONSTANT=1
=> 1
irb(main):002:0> IS_CONSTANT=2
(irb):2: warning: already initialized constant IS_CONSTANT
(irb):1: warning: previous definition of IS_CONSTANT was here
=> 2

# 多重赋值

  1. 同时对 a,b,c 变量进行赋值
多重赋值
irb(main):001:0> a, b, c = 1, 2, 3
=> [1, 2, 3]
# 即使 = 号两边数量不相等也不会报错
# 左边个数较多时,Ruby 会自动将 nil 赋值给未分配的变量
irb(main):002:0> x, y, z = 1, 2
=> [1, 2]
irb(main):003:0> p [x, y, z]
[1, 2, nil]
=> [1, 2, nil]
# 右边个数较多时,Ruby 会自动忽略多余的值
irb(main):004:0> m, n = 1, 2, 3
=> [1, 2, 3]
irb(main):005:0> p [m, n]
[1, 2]
=> [1, 2]
  1. 变量前加上 *,Ruby 会将未分配的值封装成数组赋值给该变量
多重赋值
irb(main):006:0> q, w, *t = 1, 2, 3, 4, 5
=> [1, 2, 3, 4, 5]
irb(main):007:0> p [q, w, t]
[1, 2, [3, 4, 5]]
=> [1, 2, [3, 4, 5]]
irb(main):008:0> d, *e, f = 10, 11, 12, 13, 14, 15
=> [10, 11, 12, 13, 14, 15]
irb(main):009:0> p [d, e, f]
[10, [11, 12, 13, 14], 15]
=> [10, [11, 12, 13, 14], 15]
  1. 用数组赋值时,左边有多个变量时,Ruby 会自动获取数组的元素进行多重赋值
多重赋值
irb(main):001:0> arr = [1, 2, 3]
=> [1, 2, 3]
irb(main):002:0> a, b = arr
=> [1, 2, 3]
irb(main):003:0> p [a, b]
[1, 2]
=> [1, 2]
  1. 获取嵌套数组的元素
多重赋值
irb(main):004:0> arr = ["nickname", ["age", 20], ]
=> ["nickname", ["age", 20]]
irb(main):005:0> nickname, age = arr
=> ["nickname", ["age", 20]]
irb(main):006:0> p nickname
"nickname"
=> "nickname"
irb(main):007:0> p age
["age", 20]
=> ["age", 20]
# 使用 () 包裹变量,可以再进一步将内部数组的元素值取出来
irb(main):008:0> arr = [1, [2, 3], 4,]
=> [1, [2, 3], 4]
irb(main):009:0> a, (b1, b2), c = arr
=> [1, [2, 3], 4]
irb(main):010:0> p b1
2
=> 2
irb(main):011:0> p b2
3
=> 3
irb(main):012:0>

# 条件语句

在 Ruby 中,真值可以是除 false、nil 以外的所有对象,假值只有 false、nil 两种情况

条件语句中的 then 可以省略

  1. if 语句
if语句
a = 10 
b = 20
if a > b
  puts 'a比b大'
elsif a < b
  puts 'a比b小'
else
  puts 'a等于b'
end
  1. unless 语句

和 if 语句不同,unless 语句是条件为假时进行处理

unless语句
a = 10
b = 20
unless a > b then
  puts 'a不比b大'
end
  1. case 语句

case 语句中 when 判断值相等时,实际使用的是 === 运算符。当左边是数值或字符串时 === 和 == 意义相同

case语句
tags = ['Java', 'Ruby', 'C/C++']
tags.each do |tagename|
  case tagename
  when 'Java' then
    puts 'learning Java'
  when 'Ruby' then
    puts 'learning Ruby'
  else
    puts 'learning other languages'
  end
end

# 循环语句

  1. times 方法
times方法
puts '| --times-- |'
# 1. times 循环
3.times do |i|
  puts "| 第#{i + 1}次循环 |"
end
  1. for 语句
for语句
puts '| --loop--- |'
# 2. for 循环
for i in 1..3
  puts "| 第#{i}次循环 |"
end
  1. while 语句
while语句
puts '| --while-- |'
# 3. while 循环
i = 5
while i < 8 do
  puts "| 当前值: #{i} |"
  i += 1
end
  1. until 语句

until 语句当条件不成立时才进行循环

until语句
puts '| -until- |'
# 4. until 语句
sum = 0
i = 1
until sum >= 5
  puts "| 当前sum: #{sum} |"
  sum += i
  i += 1
end
  1. each 方法
each方法
names = ["alice", "bob", "cyndi"]
names.each do |name|
  puts "'name': '#{name}'"
end
# 等价写法
names.each { |name|
  puts "'name': '#{name}'"
}
  1. break、next、redo

循环语句,一般配合 break、next、redo 使用

  • break: 终止程序,退出循环
break例子
puts "break的例子"
i = 0
langs = ["Ruby", "Rust", "Java"]
langs.each do |lang|
  i += 1
  if i == langs.size
    break
  end
  p [i, lang]
end
=begin 输出
  break 的例子
  [1, "Ruby"]
  [2, "Rust"]
=end
  • next:跳过当前循环,直接进入下一次循环
next例子
puts "next例子"
i = 0
langs = ["Ruby", "Rust", "Java"]
langs.each do |lang|
  i += 1
  if i == langs.size - 1
    next
  end
  p [i, lang]
end
=begin 输出
  next 的例子
  [1, "Ruby"]
  [3, "Java"]
=end
  • redo:再次执行一次相同的循环,不会再次进行条件判断
redo例子
puts "redo例子"
i = 0
langs = ["Ruby", "Rust", "Java"]
langs.each do |lang|
  i += 1
  if i == langs.size - 1
    redo
  end
  p [i, lang]
end
=begin 输出
  redo 的例子
  [1, "Ruby"]
  [3, "Rust"]
  [4, "Java"]
=end

# 方法

如果想深入了解 Ruby 的方法可以参考《Ruby 元编程》一书

# 定义带块的方法

带块的方法
def myloop
  while true
    yield # 执行块
  end
end
num = 1
myloop do
  break if num > 64 # ruby 特有的写法,可以将条件判断后置
  puts "num is #{num}"
  num *= 2
end

yield 是定义带块方法的关键字。调用方法时通过块传进来的处理会在 yield 定义的地方执行。
如果 yield 部分有参数,会被当作块变量传入块里。块里最后的表达式的值既是块的执行结果,
同时也可以作为 yield 的返回值在块的外部使用

# 可变参数方法

通过使用 ”* 变量名 “ 的形式来定义可变形参
可变形参会被 R 封装成数组,供方法内部使用

可变参数在方法的参数列表中只能出现一次

可变形参
def foo(*args)
  args
end
p foo(1, 2, 3) # 输出 => [1, 2, 3]

# 关键字参数

Ruby 中可以使用关键字参数定义方法的参数列表,以 "参数名:参数值" 的形式传入方法
这种形式为每个参数都指定了一个默认值,因此可以参略任何一个参数进行调用,由于参数名也传给了方法,
所以参数顺序可以自由更改

方法中使用关键字参数
# 使用关键字参数
def person(name: 'alice', age: 10, gender: 'm')
  puts "[Person] {name: #{name}, age: #{age}, gender: #{gender}}"
end
# 1. 省略所有参数
person() #=> [Person] {name: alice, age: 10, gender: m}
# 2. 改变参数传递顺序
person(gender: 'f', name: 'cyndi', age: 32) #=> [Person] {name: cyndi, age: 32, gender: f }

关键字参数只能出现参数列表的最后,如果有普通参数的话,普通参数要先定义

混用参数形式
# 下面的方法会报错:Exception::,期望出现:号也就关键字参数的形式
def person2(name: 'alice', age: 10, gender: 'm', other)
  puts "[Person] {name: #{name}, age: #{age}, gender: #{gender}, other: #{other}}"
end
# 下面是正确的使用形式
def person3(other, name: 'alice', age: 10, gender: 'm')
  puts "[Person] {name: #{name}, age: #{age}, gender: #{gender}, other: #{other}}"
end
person3('null') #=> [Person] {name: alice, age: 10, gender: m, other: null}

将参数传递给方法时,可以将数组分解后的元素作为参数传递给方法。
调用方法时使用 "* 数组 " 的形式,这时传递给方法的是数组中各个元素。
需要注意的是:数组元素传入的参数个数以及其他参数个数总和要和方法定义的参数个数一致

把数组分解为参数进行传递
def foo(a, b, c)
  a + b +c
end
p foo(1, 2, 3) #=> 6
args1 = [2, 3]
p foo(1, *args1) #=> 6
args2 = [1, 2, 3]
p foo(*args2) #=> 6
更新于 阅读次数