以下是 Ruby 基础语法的简明总结,适合快速入门:
name = "Alice"
_age = 20
//局部变量附加:{{{{
声明与命名规则
命名格式
_
开头,如 name
、_count
。class
、def
)冲突。声明方式
=
隐式声明,无需显式类型。age = 25 # 声明局部变量 age
_message = "Hello" # 声明局部变量 _message
作用域规则
代码块内外的可见性
块参数会遮蔽外部变量:
x = 10
3.times do |x| # 块参数 x 遮蔽外部变量
puts x # 输出 0, 1, 2
end
puts x # 输出 10(外部变量未被修改)
无块参数时可访问外部变量:
x = 5
3.times do
x = 10 # 修改外部变量 x
end
puts x # 输出 10
方法内的局部变量
方法内部变量对外不可见:
def test_method
local_var = "内部变量"
end
test_method
puts local_var # NameError: undefined local variable
方法无法访问定义它的外部局部变量:
outer_var = "外部变量"
def show_var
puts outer_var # NameError: undefined local variable
end
show_var
条件与循环中的变量
即使条件未执行,变量也会被声明(初始化为 nil
):
if false
a = 1 # 代码未执行,但变量 a 已声明
end
puts a # 输出 nil
循环(如 while
)不创建新作用域:
i = 0
while i < 3
inner = i
i += 1
end
puts inner # 输出 2
变量遮蔽与覆盖
内部作用域遮蔽外部变量
x = 100
1.times do
x = 200 # 直接修改外部变量 x
y = 300 # 声明新变量 y(作用域在块内)
end
puts x # 输出 200
puts y # NameError: undefined local variable
方法参数与局部变量同名
def demo(x)
x = 20 # 修改的是参数 x,不影响外部变量
puts x # 输出 20
end
x = 10
demo(x)
puts x # 输出 10
特殊场景
顶层作用域的局部变量
top_var = "顶层变量"
def show_top_var
puts top_var # NameError: undefined local variable
end
show_top_var
类/模块定义中的局部变量
class MyClass
class_var = "类定义内的局部变量"
def self.show_var
puts class_var # NameError: undefined local variable
end
end
最佳实践
user_count
而非 uc
)。总结
场景 | 行为 |
---|---|
块内无参数赋值 | 可读写外部变量 |
块带同名参数 | 遮蔽外部变量,内部操作不影响外部 |
方法内部变量 | 仅在方法内有效,外部不可见 |
条件/循环中的变量 | 即使代码未执行,变量也会被声明(值为 nil ) |
类定义中的变量 | 仅在类定义过程中有效,类方法无法访问 |
理解局部变量的作用域规则是编写可维护 Ruby 代码的基础,尤其在处理复杂逻辑时能避免意外的变量污染或覆盖。
//局部变量附加结束}}}}
@
开头,属于对象实例。@name = "Bob"
//实例变量附加:{{{{
实例变量(Instance Variables)是面向对象编程的核心概念,用于存储对象的状态。以下是其详细规则和使用方法:
定义与基本特性
命名规则
@
符号开头,如 @name
、@age
。nil
(未显式赋值时)。作用域
声明与访问
class Person
def initialize(name)
@name = name # 在 initialize 方法中初始化
end
def greet
"Hello, #{@name}!" # 在方法中访问
end
end
person = Person.new("Alice")
puts person.greet # => "Hello, Alice!"
//class Person代码的解释开始:
这段 Ruby 脚本定义了一个 Person
类,并演示了如何创建对象实例和调用方法。以下是逐行解释:
Person
类class Person
# 类体开始
end
class Person
:定义一个名为 Person
的类。initialize
def initialize(name)
@name = name # 初始化实例变量 @name
end
initialize
:类的构造方法,在调用 Person.new
时自动执行。name
:构造方法的参数,用于接收外部传入的值。@name = name
:将参数 name
赋值给实例变量 @name
。
@name
:以 @
开头的变量是实例变量,属于对象实例的私有状态。greet
def greet
"Hello, #{@name}!" # 使用实例变量 @name 拼接字符串
end
greet
:定义一个名为 greet
的实例方法。#{@name}
:字符串插值语法,将 @name
的值嵌入字符串中。person = Person.new("Alice")
Person.new("Alice")
:调用 Person
类的 new
方法创建实例。
new
方法会触发 initialize
方法,并将 "Alice"
作为参数传递。@name
被赋值为 "Alice"
。person
:变量指向新创建的 Person
实例对象。puts person.greet # => "Hello, Alice!"
person.greet
:调用 person
实例的 greet
方法。
"Hello, Alice!"
。puts
:输出字符串到控制台。//class Person代码的解释结束
getter
和 setter
:attr_reader
:生成 getter 方法。attr_writer
:生成 setter 方法。attr_accessor
:生成 getter 和 setter。class User
attr_accessor :email # 自动生成 @email 的读写方法
attr_reader :id # 只生成 @id 的读方法
def initialize(id)
@id = id
end
end
user = User.new(1)
user.email = "[email protected]"
puts user.email # => "[email protected]"
//访问器方法代码解释 开始
属性访问器(Attribute Accessors),属性访问器(Attribute Accessors)是一种元编程机制,用于快速生成实例变量的 getter
(读方法)和 setter
(写方法)。Ruby 提供了三个核心方法简化操作:
三种属性访问器
attr_reader
生成 只读方法(getter),允许外部读取实例变量。
class User
attr_reader :id # 生成 def id; @id; end
def initialize(id)
@id = id
end
end
user = User.new(1)
puts user.id # => 1
user.id = 2 # NoMethodError(无写方法)
attr_writer
生成 只写方法(setter),允许外部修改实例变量。
class User
attr_writer :email # 生成 def email=(value); @email = value; end
def initialize(email)
@email = email
end
end
user = User.new("[email protected]")
user.email = "[email protected]" # 修改成功
puts user.email # NoMethodError(无读方法)
attr_accessor
生成 读写方法(getter + setter),最常用。
class Product
attr_accessor :price # 生成读方法和写方法
def initialize(price)
@price = price
end
end
product = Product.new(100)
product.price = 150
puts product.price # => 150
访问器的底层原理
手动实现等效代码
class User
# attr_reader :name 的等效代码
def name
@name
end
# attr_writer :name 的等效代码
def name=(value)
@name = value
end
end
动态生成方法
attr_*
方法本质是通过元编程动态定义方法:
class Class
def my_attr_reader(name)
define_method(name) do
instance_variable_get("@#{name}")
end
end
end
高级用法与技巧
批量定义访问器
class Person
attr_accessor :name, :age, :gender # 多个属性
end
添加自定义逻辑
class Temperature
attr_reader :celsius
def celsius=(value)
raise "温度不能低于绝对零度" if value < -273.15
@celsius = value
end
end
temp = Temperature.new
temp.celsius = -300 # RuntimeError
结合初始化方法
class Book
attr_accessor :title, :author
def initialize(title, author)
@title = title
@author = author
end
end
book = Book.new("Ruby指南", "松本行弘")
book.title = "Ruby高级编程"
继承行为
父类的访问器方法会被子类继承:
class Admin < User
end
admin = Admin.new(1)
admin.email = "[email protected]" # 正常执行(继承 attr_accessor)
//访问器方法代码解释 结束
实例变量的特性
attr_accessor
)。obj = Object.new
obj.instance_variable_set(:@x, 10) # 动态添加 @x
puts obj.instance_variable_get(:@x) # => 10
obj.remove_instance_variable(:@x) # 删除 @x
//动态增删附加 开始:
这段 Ruby 脚本演示了如何通过反射机制 动态管理实例变量,
代码逐行解析
obj = Object.new
Object
类的匿名实例。obj
没有任何预定义的实例变量。@x
obj.instance_variable_set(:@x, 10)
instance_variable_set
方法
@
,如 :@x
)。obj
新增实例变量 @x
,值为 10
。@x
的值puts obj.instance_variable_get(:@x) # => 10
instance_variable_get
方法
:@x
)。nil
。@x
obj.remove_instance_variable(:@x)
remove_instance_variable
方法
:@x
)。NameError
。关键方法和注意事项
方法名 | 用途 | 注意事项 |
---|---|---|
instance_variable_set |
动态设置实例变量 | 变量名必须以 @ 开头,否则抛出 NameError |
instance_variable_get |
动态读取实例变量 | 变量不存在时返回 nil ,不会报错 |
remove_instance_variable |
动态删除实例变量 | 变量不存在时抛出 NameError ,需确保变量存在或使用 begin rescue 处理 |
使用场景
动态对象构造
在运行时根据条件动态添加属性:
data = { name: "Alice", age: 20 }
obj = Object.new
data.each { |key, value| obj.instance_variable_set("@#{key}", value) }
元编程和框架开发
在编写灵活的程序结构时(如 ORM、序列化工具):
class Serializer
def serialize(obj)
obj.instance_variables.each_with_object({}) do |var, hash|
hash[var] = obj.instance_variable_get(var)
end
end
end
调试和探索性编程
快速查看或修改对象内部状态:
user = User.find(1)
user.instance_variable_set(:@password, "hacked") # 危险操作!仅用于演示
obj = Object.new
obj.instance_variable_set(:@不存在的方法, 100) # 合法但可能导致后续逻辑混乱
# 使用下判断
if obj.instance_variable_defined?(:@x)
obj.remove_instance_variable(:@x)
end
// 动态增删附加 结束
@var
) | 类变量 (@@var
) |高级用法
class Dog
def initialize(name)
@name = name
end
end
dog = Dog.new("Buddy")
# 获取所有实例变量名
dog.instance_variables # => [:@name]
# 检查是否存在实例变量
dog.instance_variable_defined?(:@name) # => true
module Loggable
def log(message)
@logs ||= [] # 若 @logs 不存在则初始化为空数组
@logs << message
end
end
class Service
include Loggable
end
service = Service.new
service.log("Event 1")
service.instance_variable_get(:@logs) # => ["Event 1"]
注意事项
避免未初始化访问
实例变量未赋值时为 nil
,需注意空值问题:
class Product
def print_price
"Price: #{@price}" # @price 未初始化时为 nil
end
end
Product.new.print_price # => "Price: "
命名冲突
子类可能意外覆盖父类的实例变量:
class Animal
def initialize
@name = "Animal"
end
end
class Cat < Animal
def initialize
@name = "Cat" # 覆盖父类的 @name
end
end
总结
场景 | 实例变量的行为 |
---|---|
对象初始化 | 通过 initialize 方法赋值 |
方法间共享 | 同一对象的实例方法均可访问 |
动态管理 | 支持运行时增删 |
封装性 | 必须通过方法暴露给外部 |
实例变量是 Ruby 面向对象的核心机制,合理使用它们可以高效管理对象状态!
//实例变量附加结束}}}}
@@
开头,属于整个类。@@count = 0
// 类变量 附加开始{{{{
在 Ruby 中,类变量(Class Variables)是一种特殊类型的变量,用于在类层级共享数据。
定义与基本特性
命名规则
@@
开头,如 @@count
、@@config
。NameError
)。作用域
基本用法示例
class Counter
@@count = 0 # 初始化类变量
def self.increment
@@count += 1
end
def self.total
@@count
end
end
Counter.increment
Counter.increment
puts Counter.total # => 2
class User
@@users = []
def initialize(name)
@name = name
@@users << self # 将实例自身加入类变量数组
end
def self.all_users
@@users
end
end
alice = User.new("Alice")
bob = User.new("Bob")
puts User.all_users.size # => 2
类变量的继承行为
class Parent
@@value = 100
def self.value
@@value
end
end
class Child < Parent
def self.change_value
@@value = 200
end
end
Child.change_value
puts Parent.value # => 200(父类的类变量被子类修改)
class A
@@list = []
end
class B < A; end
class C < A; end
B.class_variable_get(:@@list) << "item"
puts C.class_variable_get(:@@list) # => ["item"]
类变量的替代方案:类实例变量
由于类变量的共享特性容易导致意外修改,Ruby 开发者常使用 类实例变量 作为替代:
@
开头,属于类对象(而非类本身)。attr_accessor
定义。class Parent
@count = 0 # 类实例变量
class << self
attr_accessor :count # 定义类实例变量的访问器
end
end
class Child < Parent; end
Parent.count = 5
Child.count = 10
puts Parent.count # => 5(不受子类影响)
puts Child.count # => 10
类变量使用场景
场景 | 示例 |
---|---|
全局类级计数器 | 统计实例数量、方法调用次数 |
共享配置 | 数据库连接、日志级别设置 |
缓存数据 | 存储类级别的计算结果或临时数据 |
注意事项与陷阱
初始化位置
类变量必须在类或模块内部初始化(不能在其他作用域)。
class Demo
@@value = 0 # 正确:在类体内初始化
end
# @@value = 0 # 错误:顶层作用域无法初始化类变量
线程安全问题
类变量在多线程环境中可能引发竞态条件,需加锁保护:
class Counter
@@mutex = Mutex.new
@@count = 0
def self.safe_increment
@@mutex.synchronize { @@count += 1 }
end
end
避免过度共享
类变量的全局性容易导致代码耦合,应谨慎使用。
总结对比
特性 | 类变量 (@@var ) |
类实例变量 (@var ) |
---|---|---|
作用域 | 类及其所有子类共享 | 仅在定义它的类中有效 |
继承行为 | 子类修改影响父类和其他子类 | 不继承,每个类独立 |
初始化位置 | 必须在类或模块内部 | 可在类方法或类体内初始化 |
适用场景 | 需要跨继承树共享数据 | 需要类级别的私有状态 |
//类变量 附加结束}}}}
全局变量
以 $
开头,作用域全局。
$debug_mode = true
常量
全大写字母,约定不可修改(修改会警告)。
PI = 3.14159
字符串(String)
单引号(不转义)或双引号(支持转义和插值)。
str1 = 'Hello \n World' # 输出换行符
str2 = "Hello #{name}" # 插值:Hello Alice
符号(Symbol)
轻量级字符串,以 :
开头,常用于哈希键。
:user_id
数组(Array)
有序集合,通过索引访问。
nums = [1, 2, 3]
nums[0] # => 1
哈希(Hash)
键值对集合,键可以是任意对象。
person = { name: "Alice", age: 20 }
person[:name] # => "Alice"
范围(Range)
表示连续区间,常用于迭代。
(1..5).each { |n| puts n } # 1到5
(1...5).each { |n| puts n } # 1到4
算术运算符
+
, -
, *
, /
, %
, **
(幂运算)。
2 ** 3 # => 8
10 % 3 # => 1
比较运算符
==
, !=
, >
, <
, >=
, <=
, <=>
(返回 -1, 0, 1)。
5 <=> 3 # => 1(5 > 3)
逻辑运算符
&&
, ||
, !
(也可用 and
, or
, not
,但优先级不同)。
true && false # => false
赋值运算符
=
, +=
, -=
, *=
, /=
, %=
。
x = 5
x += 3 # => 8
条件判断
# if/elsif/else
if age >= 18
puts "Adult"
elsif age > 0
puts "Child"
else
puts "Invalid"
end
# 三元运算符
result = (score > 60) ? "Pass" : "Fail"
循环
# while 循环
i = 0
while i < 3
puts i
i += 1
end
# until 循环
until i >= 3
puts i
i += 1
end
# for 循环(较少使用)
for num in [1, 2, 3]
puts num
end
迭代器
# each 方法
(1..3).each { |n| puts n }
# map 方法
doubled = [1, 2, 3].map { |n| n * 2 } # => [2, 4, 6]
基本语法
def greet(name)
"Hello, #{name}!"
end
greet("Ruby") # => "Hello, Ruby!"
默认参数
def add(a, b = 1)
a + b
end
add(3) # => 4
add(3, 5) # => 8
可变参数
def sum(*nums)
nums.sum
end
sum(1, 2, 3) # => 6
begin
# 可能出错的代码
result = 10 / 0
rescue ZeroDivisionError => e
puts "Error: #{e.message}"
ensure
puts "Cleanup code here"
end
单行注释
# 这是一个注释
多行注释
=begin
这是一个多行注释
可以写多行内容
=end
% 符号快捷语法
%w[apple banana cherry] # => ["apple", "banana", "cherry"](字符串数组)
%i[red green blue] # => [:red, :green, :blue](符号数组)
并行赋值
a, b = 1, 2 # a=1, b=2
a, b = b, a # 交换值:a=2, b=1
使用 {}
或 do...end
# 单行用 {}
[1, 2, 3].each { |n| puts n }
# 多行用 do...end
[1, 2, 3].each do |n|
puts "Number: #{n}"
end
自定义接受块的方法
def repeat(times)
times.times { yield } # yield 调用块
end
repeat(3) { puts "Hello!" } # 输出 3 次 Hello
字符串操作
"ruby".upcase # => "RUBY"
"HELLO".downcase # => "hello"
" test ".strip # => "test"
数组操作
[1, 2, 3].include?(2) # => true
[1, 2, 3].push(4) # => [1, 2, 3, 4]
[1, 2, 3].join("-") # => "1-2-3"
以下是 Ruby 的 全部关键字列表(基于 Ruby 3.x 版本),这些单词具有特殊语法含义,不可用作变量名或方法名:
控制流
关键字 | 说明 |
---|---|
if |
条件判断 |
else |
条件分支 |
elsif |
多条件分支 |
unless |
反向条件判断 |
case |
多条件匹配 |
when |
case 语句的分支条件 |
then |
简化条件语法 |
end |
结束代码块 |
循环与迭代
关键字 | 说明 |
---|---|
while |
条件循环 |
until |
反向条件循环 |
for |
遍历循环(较少使用) |
in |
用于 for 或 case |
do |
定义循环/块的开始 |
break |
跳出循环 |
next |
跳过当前迭代 |
redo |
重新执行当前迭代 |
retry |
重新开始循环(已废弃) |
类与模块
关键字 | 说明 |
---|---|
class |
定义类 |
module |
定义模块 |
def |
定义方法 |
undef |
取消方法定义 |
alias |
方法别名 |
super |
调用父类方法 |
self |
当前对象 |
异常处理
关键字 | 说明 |
---|---|
begin |
异常处理块开始 |
rescue |
捕获异常 |
ensure |
确保执行(类似 finally) |
raise |
抛出异常 |
throw |
抛出符号(与 catch 配合) |
catch |
捕获符号 |
访问控制
关键字 | 说明 |
---|---|
public |
公开方法 |
private |
私有方法 |
protected |
受保护方法 |
逻辑与运算符
关键字 | 说明 |
---|---|
and |
逻辑与(低优先级) |
or |
逻辑或(低优先级) |
not |
逻辑非 |
true |
布尔真值 |
false |
布尔假值 |
nil |
空值 |
其他核心关键字
关键字 | 说明 |
---|---|
return |
从方法返回值 |
yield |
调用块 |
__FILE__ |
当前文件名(伪变量) |
__LINE__ |
当前行号(伪变量) |
BEGIN |
程序启动前执行的代码块 |
END |
程序退出前执行的代码块 |
defined? |
检查标识符是否已定义 |
模式匹配(Ruby 2.7+)
关键字 | 说明 |
---|---|
in |
模式匹配分支 |
注意:
非关键字但需谨慎使用:
puts
、gets
等是全局方法,而非关键字。
proc
、lambda
是类或方法,可被覆盖(但强烈建议不要这样做)。
版本差异:
retry
在循环中已废弃(但仍可用于 begin/rescue
块)。
in
在 Ruby 2.7+ 中用于模式匹配。
完整列表(按字母排序):
__FILE__, __LINE__, BEGIN, END, alias, and, begin, break, case, catch, class, def, defined?, do, else, elsif, end, ensure, false, for, if, in, module, next, nil, not, or, redo, rescue, retry, return, self, super, then, true, undef, unless, until, when, while, yield
Ruby 语法以简洁灵活著称,核心特点是:
end
结束。建议通过实际编码练习巩固语法,例如尝试编写小型脚本或使用 Ruby Playground 在线工具。
— END —