Ruby变量 #

一、变量概述 #

Ruby是一种动态类型语言,变量不需要声明类型,可以直接赋值使用。变量的类型由赋值的对象决定,并且可以在运行时改变。

ruby
x = 10
x = "hello"
x = [1, 2, 3]

二、变量类型 #

Ruby有五种变量类型,通过前缀区分:

类型 前缀 作用域 示例
局部变量 方法/块内 name
实例变量 @ 对象内 @name
类变量 @@ 类及子类 @@count
全局变量 $ 整个程序 $debug
常量 大写开头 取决于定义位置 MAX_SIZE

2.1 局部变量 #

局部变量在方法、块或类定义内部有效。

ruby
def greet
  name = "Ruby"
  puts "Hello, #{name}"
end

greet
name = "Global"
puts name

[1, 2, 3].each do |n|
  result = n * 2
  puts result
end

局部变量的作用域规则:

ruby
x = 1

def my_method
  x = 10
  puts "方法内: #{x}"
end

my_method
puts "方法外: #{x}"

[1, 2, 3].each do |i|
  x = i
  puts "块内: #{x}"
end

puts "块外: #{x}"

2.2 实例变量 #

实例变量以 @ 开头,属于对象实例,在对象内部共享。

ruby
class Person
  def initialize(name, age)
    @name = name
    @age = age
  end

  def introduce
    puts "我是#{@name},今年#{@age}岁"
  end

  def name
    @name
  end

  def name=(new_name)
    @name = new_name
  end
end

person = Person.new("Ruby", 25)
person.introduce
person.name = "Rails"
person.introduce

实例变量的特点:

ruby
class Counter
  def increment
    @count ||= 0
    @count += 1
  end

  def count
    @count || 0
  end
end

c1 = Counter.new
c2 = Counter.new

c1.increment
c1.increment
c2.increment

puts c1.count
puts c2.count

2.3 类变量 #

类变量以 @@ 开头,在类及其所有实例、子类之间共享。

ruby
class Animal
  @@count = 0

  def initialize
    @@count += 1
  end

  def self.count
    @@count
  end
end

class Dog < Animal
  def initialize
    super
    puts "创建了一只狗"
  end
end

class Cat < Animal
  def initialize
    super
    puts "创建了一只猫"
  end
end

Dog.new
Cat.new
Dog.new

puts "总共有 #{Animal.count} 只动物"

类变量的注意事项:

ruby
class Parent
  @@value = "parent"

  def self.value
    @@value
  end
end

class Child < Parent
  @@value = "child"
end

puts Parent.value
puts Child.value

2.4 全局变量 #

全局变量以 $ 开头,在整个程序中可访问。

ruby
$debug = true

def log(message)
  puts "[DEBUG] #{message}" if $debug
end

class App
  def run
    log "应用启动"
  end
end

App.new.run
$debug = false
App.new.run

预定义的全局变量:

变量 含义
$0 当前脚本名
$* 命令行参数数组
$? 上一个子进程的退出状态
$_ gets读取的最后一行
$. 当前读取的行号
$! 当前异常信息
$@ 异常的backtrace
$~ 最后一次匹配结果
$& 最后一次匹配的字符串
$1, $2 正则捕获组
$stdin 标准输入
$stdout 标准输出
$stderr 标准错误
ruby
puts "脚本名: #{$0}"
puts "参数: #{$*}"

2.5 常量 #

常量以大写字母开头,值不应该被修改。

ruby
MAX_SIZE = 100
DEFAULT_NAME = "Ruby"
PI = 3.14159265359

class Config
  VERSION = "1.0.0"
  API_URL = "https://api.example.com"
end

puts MAX_SIZE
puts Config::VERSION

常量的警告:

ruby
NAME = "Ruby"
NAME = "Rails"

输出:

text
warning: already initialized constant NAME

冻结常量:

ruby
COLORS = ["red", "green", "blue"].freeze
COLORS << "yellow"

三、变量命名规则 #

3.1 基本规则 #

  • 以字母或下划线开头
  • 后续可以是字母、数字或下划线
  • 区分大小写
ruby
name = "valid"
_name = "valid"
name123 = "valid"
my_name = "valid"
名前 = "valid"

1name = "invalid"
@ = "invalid"

3.2 命名约定 #

ruby
# 局部变量:snake_case
user_name = "Ruby"
total_count = 100

# 实例变量:@snake_case
@user_name = "Ruby"

# 类变量:@@snake_case
@@instance_count = 0

# 全局变量:$snake_case
$global_config = {}

# 常量:SCREAMING_SNAKE_CASE
MAX_CONNECTIONS = 100
DEFAULT_TIMEOUT = 30

# 类/模块名:PascalCase
class UserAccount
end

module PaymentGateway
end

3.3 语义化命名 #

ruby
# 好的命名
user_count = 10
is_active = true
total_price = 99.99

# 不好的命名
x = 10
flag = true
tp = 99.99

四、变量作用域详解 #

4.1 作用域门 #

Ruby有三个作用域门:classmoduledef

ruby
v1 = 1

class MyClass
  v2 = 2

  def my_method
    v3 = 3
  end
end

v1可访问
v2不可访问
v3不可访问

4.2 作用域穿透 #

使用 Class.newModule.newdefine_method 可以穿透作用域:

ruby
v1 = 1

MyClass = Class.new do
  v2 = 2
  puts "类内: v1=#{v1}, v2=#{v2}"

  define_method :my_method do
    v3 = 3
    puts "方法内: v1=#{v1}, v2=#{v2}, v3=#{v3}"
  end
end

obj = MyClass.new
obj.my_method

4.3 块的作用域 #

块可以访问外部变量:

ruby
x = 1

[1, 2, 3].each do |n|
  puts x
  x = n
end

puts x

4.4 Proc和Lambda的作用域 #

ruby
def create_counter
  count = 0
  -> { count += 1 }
end

counter = create_counter
puts counter.call
puts counter.call
puts counter.call

五、并行赋值 #

5.1 基本并行赋值 #

ruby
a, b = 1, 2
puts a
puts b

a, b = b, a
puts a
puts b

5.2 数组解构 #

ruby
arr = [1, 2, 3]
a, b, c = arr
puts a, b, c

a, *rest = [1, 2, 3, 4, 5]
puts a
p rest

first, *, last = [1, 2, 3, 4, 5]
puts first
puts last

5.3 嵌套解构 #

ruby
a, (b, c) = [1, [2, 3]]
puts a
puts b
puts c

5.4 方法返回多值 #

ruby
def min_max(arr)
  [arr.min, arr.max]
end

min, max = min_max([3, 1, 4, 1, 5, 9])
puts "最小值: #{min}, 最大值: #{max}"

六、特殊变量 #

6.1 self #

self 指向当前对象:

ruby
class Person
  def initialize(name)
    @name = name
  end

  def introduce
    puts "我是 #{self.class} 的实例"
  end

  def self.create(name)
    self.new(name)
  end
end

p = Person.new("Ruby")
p.introduce

6.2 nil #

nil 表示"无值":

ruby
x = nil
puts x.nil?
puts x.class

def find_user(id)
  nil
end

user = find_user(1)
if user
  puts "找到用户"
else
  puts "用户不存在"
end

七、变量最佳实践 #

7.1 避免全局变量 #

ruby
# 不好
$counter = 0

def increment
  $counter += 1
end

# 好
class Counter
  attr_reader :count

  def initialize
    @count = 0
  end

  def increment
    @count += 1
  end
end

7.2 谨慎使用类变量 #

ruby
# 类变量在继承中可能产生意外行为
class Parent
  @@value = "parent"
end

class Child < Parent
  @@value = "child"
end

# 使用类实例变量替代
class Parent
  @value = "parent"

  def self.value
    @value
  end
end

7.3 使用attr系列方法 #

ruby
class Person
  attr_reader :name
  attr_writer :email
  attr_accessor :age

  def initialize(name, age)
    @name = name
    @age = age
  end
end

person = Person.new("Ruby", 25)
puts person.name
person.age = 26
person.email = "ruby@example.com"

八、总结 #

本章我们学习了:

  1. 变量类型:局部变量、实例变量、类变量、全局变量、常量
  2. 命名规则:snake_case、PascalCase、SCREAMING_SNAKE_CASE
  3. 作用域:作用域门、块作用域、闭包
  4. 并行赋值:解构、交换变量
  5. 最佳实践:避免全局变量、使用attr方法

接下来让我们学习Ruby的数字类型!

最后更新:2026-03-27