Ruby基础
Ruby 是一种动态、面向对象的编程语言,广泛用于Web开发,特别是通过Ruby on Rails框架。
在 Ruby 中,注释是程序员在代码中添加的文本,解释代码的功能或提供额外的信息。注释不会被解释器执行。Ruby 支持单行注释和多行注释。
单行注释以 #
开头,#
后面的所有内容都会被视为注释。
# 这是一个单行注释puts "Hello, Ruby!" # 这也是一个单行注释
多行注释以 =begin
开头,以 =end
结尾,适用于需要注释多行内容的情况。
=begin这是一个多行注释的示例。它可以用于注释多行代码或提供详细的文档。=end
puts "This is Ruby!"
注释的最佳实践
Section titled “注释的最佳实践”- 简洁明了:注释应该清晰、简洁地说明代码的功能或逻辑。
- 保持同步:当修改代码时,应同时更新相关注释,确保注释与代码一致。
- 避免过多注释:注释应当有必要且有意义,过多的注释可能会使代码难以阅读。
以下是一个带有注释的示例代码,演示了如何使用注释来解释代码的功能:
# 定义一个方法,计算两个数的和def sum(a, b) # 返回 a 和 b 的和 return a + bend
# 调用 sum 方法,并将结果输出到控制台result = sum(3, 4) # 3 和 4 的和是 7puts "The sum is #{result}" # 输出结果
Ruby 社区通常使用 RDoc 格式编写文档注释,这样可以生成 HTML 格式的文档。
# This is a sample class for demonstration.## Example:# person = Person.new("Alice", 30)# puts person.introduceclass Person # Initializes a new Person object. # # @param name [String] The name of the person. # @param age [Integer] The age of the person. def initialize(name, age) @name = name @age = age end
# Returns a greeting message. # # @return [String] A greeting message. def introduce "Hi, I'm #{@name} and I'm #{@age} years old." endend
在 Ruby 中,变量的定义非常灵活,不需要事先声明类型。以下是不同类型的变量及其定义方式:
1. 局部变量
Section titled “1. 局部变量”局部变量以小写字母或下划线开头,仅在定义它们的方法或代码块中有效。
name = "Alice"age = 25
2. 全局变量
Section titled “2. 全局变量”全局变量以 $
符号开头,可以在程序的任何地方访问。这种变量的使用要谨慎,因为它们可能会导致代码难以维护。
$global_var = "I am accessible everywhere"
3. 实例变量
Section titled “3. 实例变量”实例变量以 @
符号开头,在类的实例中定义和使用。每个实例都有自己的一组实例变量。
class Person def initialize(name, age) @name = name @age = age end
def display_info puts "Name: #{@name}, Age: #{@age}" endend
person = Person.new("Bob", 30)person.display_info # 输出: Name: Bob, Age: 30
4. 类变量
Section titled “4. 类变量”类变量以 @@
符号开头,在类的所有实例之间共享。这些变量在类定义中使用。
class Person @@count = 0
def initialize(name, age) @name = name @age = age @@count += 1 end
def self.count @@count endend
person1 = Person.new("Alice", 25)person2 = Person.new("Bob", 30)
puts Person.count # 输出: 2
常量以大写字母开头,通常在类或模块中定义。尽管常量可以被改变,但这会触发警告。
PI = 3.14
class MathConstants E = 2.71end
puts PI # 输出: 3.14puts MathConstants::E # 输出: 2.71
6. 并行赋值
Section titled “6. 并行赋值”Ruby 允许一次定义多个变量,并同时赋值。
a, b, c = 1, 2, 3puts a # 输出: 1puts b # 输出: 2puts c # 输出: 3
# 交换变量的值a, b = b, aputs a # 输出: 2puts b # 输出: 1
7. 变量作用域
Section titled “7. 变量作用域”变量的作用域取决于它们的定义位置和类型:
- 局部变量的作用域在方法、代码块或当前上下文中。
- 全局变量的作用域在整个程序中。
- 实例变量的作用域在类的实例中。
- 类变量的作用域在类的所有实例中。
- 常量的作用域在定义它们的类或模块中。
class Example CONST_VAR = "I am a constant" # 常量
def initialize @instance_var = "I am an instance variable" # 实例变量 end
def display local_var = "I am a local variable" # 局部变量 puts local_var puts @instance_var puts CONST_VAR puts $global_var # 全局变量 endend
$global_var = "I am accessible everywhere" # 定义全局变量
example = Example.newexample.display
类型 | 描述 | 示例 |
---|---|---|
Integer | 整数,无小数部分的数字 | a = 42 , b = -7 , c = 0 |
Float | 浮点数,有小数部分的数字 | x = 3.14 , y = -2.718 , z = 0.0 |
String | 字符串,一系列字符 | str1 = "Hello, world!" , str2 = 'Ruby is fun.' |
Symbol | 符号,唯一的标识符 | sym1 = :my_symbol , sym2 = :"another symbol" |
Boolean | 布尔值,表示真或假 | is_ruby_fun = true , is_python_fun = false |
Array | 数组,有序的元素集合 | arr = [1, 2, 3, "four", 5.0] |
Hash | 哈希,键值对集合 | hash = {name: "Alice", age: 30} , hash2 = {"name" => "Bob", "age" => 25} |
Range | 范围,一个区间 | range1 = 1..5 , range2 = 'a'..'z' , range3 = 1...5 |
Nil | 表示无或没有值 | nothing = nil |
Time | 时间,表示日期和时间 | current_time = Time.now , past_time = Time.new(2000, 1, 1) |
Regexp | 正则表达式,表示匹配模式 | regex = /[a-z]+/ |
File | 文件对象,用于文件操作 | file = File.open("example.txt", "r") |
Class | 类对象 | my_class = String |
Module | 模块对象 | my_module = Enumerable |
Proc | 可调用的代码块 | proc_example = Proc.new { |x| x * 2 } |
Lambda | Lambda,可调用的代码块 | lambda_example = -> (x) { x * 2 } |
运算符 | 描述 | 示例 |
---|---|---|
+ | 加 | 2 + 3 |
- | 减 | 5 - 2 |
* | 乘 | 3 * 4 |
/ | 除 | 10 / 2 |
% | 取模 | 10 % 3 |
** | 幂 | 2 ** 3 |
运算符 | 描述 | 示例 |
---|---|---|
== | 相等 | 5 == 5 |
!= | 不相等 | 5 != 3 |
> | 大于 | 5 > 3 |
< | 小于 | 3 < 5 |
>= | 大于或等于 | 5 >= 5 |
<= | 小于或等于 | 3 <= 5 |
<=> | 比较(组合比较符) | 5 <=> 3 |
=== | 相同(case 语句中) | (1..5) === 3 |
运算符 | 描述 | 示例 |
---|---|---|
= | 赋值 | a = 5 |
+= | 加并赋值 | a += 3 |
-= | 减并赋值 | a -= 2 |
*= | 乘并赋值 | a *= 4 |
/= | 除并赋值 | a /= 2 |
%= | 取模并赋值 | a %= 3 |
**= | 幂并赋值 | a **= 2 |
运算符 | 描述 | 示例 |
---|---|---|
&& | 逻辑与 | true && false |
|| | 逻辑或 | true || false |
! | 逻辑非 | !true |
and | 逻辑与(低优先级) | true and false |
or | 逻辑或(低优先级) | true or false |
not | 逻辑非(低优先级) | not true |
运算符 | 描述 | 示例 |
---|---|---|
& | 位与 | 5 & 3 |
| | 位或 | 5 | 3 |
^ | 位异或 | 5 ^ 3 |
~ | 位非 | ~5 |
<< | 左移 | 5 << 1 |
>> | 右移 | 5 >> 1 |
运算符 | 描述 | 示例 |
---|---|---|
.. | 范围(包含结束值) | (1..5).to_a |
... | 范围(不包含结束值) | (1...5).to_a |
? : | 三元条件运算符 | true ? 'yes' : 'no' |
defined? | 检查变量是否已定义 | defined? a |
=~ | 正则表达式匹配 | /abc/ =~ 'abcdef' |
!~ | 正则表达式不匹配 | /abc/ !~ 'defghi' |
to_i
:转换为整数to_f
:转换为浮点数
str = "123"str.to_i # 123
str = "45.67"str.to_f # 45.67
num = 123.45num.to_i # 123
to_s
:转换为字符串
num = 123num.to_s # "123"
float_num = 45.67float_num.to_s # "45.67"
to_sym
或intern
:转换为符号to_s
:符号转换为字符串
str = "hello"str.to_sym # :hello
sym = :worldsym.to_s # "world"
to_a
:转换为数组
range = (1..5)range.to_a # [1, 2, 3, 4, 5]
hash = {a: 1, b: 2}hash.to_a # [[:a, 1], [:b, 2]]
to_h
:转换为哈希
arr = [[:a, 1], [:b, 2]]arr.to_h # {:a=>1, :b=>2}
!!
:将值转换为布尔值
value = "hello"!!value # true
value = nil!!value # false
以下是一个综合示例,展示了不同类型之间的转换:
# 数字到字符串num = 123str = num.to_s # "123"
# 字符串到整数和浮点数str_num = "456"int_num = str_num.to_i # 456float_num = str_num.to_f # 456.0
# 字符串到符号str_sym = "ruby"sym = str_sym.to_sym # :ruby
# 符号到字符串sym_str = sym.to_s # "ruby"
# 数组到哈希arr = [[:a, 1], [:b, 2]]hash = arr.to_h # {:a=>1, :b=>2}
# 范围到数组range = (1..5)arr_from_range = range.to_a # [1, 2, 3, 4, 5]
# 哈希到数组hash_to_arr = hash.to_a # [[:a, 1], [:b, 2]]
# 任意值到布尔值value = "something"bool_value = !!value # true
value = nilbool_value = !!value # false
字符串格式化
Section titled “字符串格式化”在 Ruby 中,有多种方法可以对字符串进行格式化,以便将变量或表达式的值插入到字符串中。以下是一些常见的字符串格式化方法:
1. 插值(Interpolation)
Section titled “1. 插值(Interpolation)”插值是 Ruby 中最常用的字符串格式化方法。它允许在双引号字符串或反引号字符串中插入变量或表达式的值。插值使用 #{}
语法。
name = "Alice"age = 30
puts "My name is #{name} and I am #{age} years old." # 输出: My name is Alice and I am 30 years old.
2. printf
和 sprintf
Section titled “2. printf 和 sprintf”printf
和 sprintf
函数类似于 C 语言中的格式化输出函数。printf
直接输出格式化后的字符串,而 sprintf
则返回格式化后的字符串。
name = "Alice"age = 30height = 1.75
# printf 直接输出格式化后的字符串printf("Name: %s, Age: %d, Height: %.2f meters\n", name, age, height)
# sprintf 返回格式化后的字符串formatted_string = sprintf("Name: %s, Age: %d, Height: %.2f meters", name, age, height)puts formatted_string
3. format
方法
Section titled “3. format 方法”format
方法是 sprintf
的别名,用于返回格式化后的字符串。
name = "Alice"age = 30height = 1.75
formatted_string = format("Name: %s, Age: %d, Height: %.2f meters", name, age, height)puts formatted_string # 输出: Name: Alice, Age: 30, Height: 1.75 meters
4. String#%
运算符
Section titled “4. String#% 运算符”String#%
运算符可以用于格式化字符串。它与 printf
和 sprintf
类似,但语法更加简洁。
name = "Alice"age = 30height = 1.75
formatted_string = "Name: %s, Age: %d, Height: %.2f meters" % [name, age, height]puts formatted_string # 输出: Name: Alice, Age: 30, Height: 1.75 meters
5. String#rjust
, String#ljust
, String#center
Section titled “5. String#rjust, String#ljust, String#center”这些方法用于对字符串进行对齐。
str = "Ruby"
puts str.rjust(10) # 输出: " Ruby"puts str.ljust(10) # 输出: "Ruby "puts str.center(10) # 输出: " Ruby "
6. 使用 String#concat
Section titled “6. 使用 String#concat”String#concat
方法用于将多个字符串拼接在一起。
str1 = "Hello"str2 = "World"str1.concat(", ", str2, "!")
puts str1 # 输出: Hello, World!
以下是一个综合示例,展示了上述不同方法的使用:
name = "Bob"age = 25balance = 1234.56
# 插值puts "Name: #{name}, Age: #{age}, Balance: $#{balance}"
# printfprintf("Name: %s, Age: %d, Balance: $%.2f\n", name, age, balance)
# sprintf 和 formatformatted_str = sprintf("Name: %s, Age: %d, Balance: $%.2f", name, age, balance)puts formatted_str
formatted_str2 = format("Name: %s, Age: %d, Balance: $%.2f", name, age, balance)puts formatted_str2
# % 运算符formatted_str3 = "Name: %s, Age: %d, Balance: $%.2f" % [name, age, balance]puts formatted_str3
# rjust, ljust, centerputs name.rjust(10)puts name.ljust(10)puts name.center(10)
在 Ruby 中,数组是一种用于存储有序元素集合的对象。数组可以包含任意类型的元素,包括数字、字符串、符号、其他数组,甚至是哈希。以下是有关 Ruby 数组的详细介绍,包括创建数组、访问元素、常用方法和操作等。
可以使用方括号 []
或 Array.new
方法来创建数组。
# 使用方括号创建数组arr1 = [1, 2, 3, 4, 5]
# 使用 Array.new 创建数组arr2 = Array.new # 创建一个空数组arr3 = Array.new(3) # 创建一个包含3个 nil 元素的数组arr4 = Array.new(3, "default") # 创建一个包含3个 "default" 元素的数组
可以使用索引来访问数组中的元素,索引从 0 开始。
arr = [10, 20, 30, 40, 50]
puts arr[0] # 输出: 10puts arr[2] # 输出: 30puts arr[-1] # 输出: 50 (最后一个元素)puts arr[1..3] # 输出: [20, 30, 40] (索引从1到3的子数组)
可以通过索引来修改数组中的元素。
arr = [1, 2, 3, 4, 5]
arr[0] = 10puts arr # 输出: [10, 2, 3, 4, 5]
arr[1..3] = [20, 30]puts arr # 输出: [10, 20, 30, 5]
添加和删除元素
Section titled “添加和删除元素”可以使用多种方法来添加和删除数组中的元素。
arr = [1, 2, 3]
# 添加元素arr.push(4) # 或 arr << 4puts arr # 输出: [1, 2, 3, 4]
arr.unshift(0)puts arr # 输出: [0, 1, 2, 3, 4]
arr.insert(2, "new")puts arr # 输出: [0, 1, "new", 2, 3, 4]
# 删除元素arr.popputs arr # 输出: [0, 1, "new", 2, 3]
arr.shiftputs arr # 输出: [1, "new", 2, 3]
arr.delete_at(1)puts arr # 输出: [1, 2, 3]
Ruby 提供了许多数组方法,可以方便地对数组进行操作。
arr = [5, 3, 8, 2, 4]
# 长度puts arr.length # 输出: 5
# 反转puts arr.reverse # 输出: [4, 2, 8, 3, 5]
# 排序puts arr.sort # 输出: [2, 3, 4, 5, 8]
# 唯一元素arr2 = [1, 2, 2, 3, 4, 4]puts arr2.uniq # 输出: [1, 2, 3, 4]
# 合并数组arr3 = [9, 10]puts arr + arr3 # 输出: [5, 3, 8, 2, 4, 9, 10]
# 数组包含元素puts arr.include?(3) # 输出: true
# 转换为字符串puts arr.join(", ") # 输出: "5, 3, 8, 2, 4"
可以使用 each
方法来遍历数组中的元素。
arr = [1, 2, 3, 4, 5]
arr.each do |element| puts elementend
数组可以包含其他数组,从而形成多维数组。
multi_arr = [[1, 2], [3, 4], [5, 6]]
puts multi_arr[0][1] # 输出: 2puts multi_arr[2][0] # 输出: 5
以下是一个综合示例,展示了数组的创建、修改和常用方法:
# 创建数组arr = [1, 2, 3, 4, 5]
# 访问和修改元素puts arr[0] # 输出: 1arr[1] = 10puts arr # 输出: [1, 10, 3, 4, 5]
# 添加和删除元素arr.push(6)puts arr # 输出: [1, 10, 3, 4, 5, 6]arr.popputs arr # 输出: [1, 10, 3, 4, 5]
# 常用方法puts arr.length # 输出: 5puts arr.sort # 输出: [1, 3, 4, 5, 10]puts arr.include?(3) # 输出: true
# 迭代arr.each do |element| puts elementend
在 Ruby 中,哈希(Hash)是一种用于存储键值对的集合。哈希中的每个键(key)都是唯一的,而每个键对应的值(value)可以是任何对象类型。以下是有关 Ruby 哈希的详细介绍,包括创建哈希、访问和修改元素、常用方法等。
可以使用大括号 {}
或 Hash.new
方法来创建哈希。
# 使用大括号创建哈希hash1 = { "name" => "Alice", "age" => 30, "city" => "Wonderland" }
# 使用符号作为键hash2 = { name: "Bob", age: 25, city: "Paris" }
# 使用 Hash.new 创建哈希hash3 = Hash.new # 创建一个空哈希hash4 = Hash.new("default_value") # 创建一个默认值为 "default_value" 的哈希
访问和修改元素
Section titled “访问和修改元素”可以通过键来访问和修改哈希中的元素。
hash = { name: "Alice", age: 30, city: "Wonderland" }
# 访问元素puts hash[:name] # 输出: Aliceputs hash[:age] # 输出: 30
# 修改元素hash[:age] = 31puts hash[:age] # 输出: 31
# 添加新元素hash[:country] = "Wonderland"puts hash # 输出: {:name=>"Alice", :age=>31, :city=>"Wonderland", :country=>"Wonderland"}
可以使用 delete
方法删除哈希中的元素。
hash = { name: "Alice", age: 30, city: "Wonderland" }
# 删除元素hash.delete(:age)puts hash # 输出: {:name=>"Alice", :city=>"Wonderland"}
Ruby 提供了许多哈希方法,可以方便地对哈希进行操作。
hash = { name: "Alice", age: 30, city: "Wonderland" }
# 获取所有键puts hash.keys # 输出: [:name, :age, :city]
# 获取所有值puts hash.values # 输出: ["Alice", 30, "Wonderland"]
# 合并两个哈希hash2 = { country: "Wonderland", occupation: "Developer" }merged_hash = hash.merge(hash2)puts merged_hash # 输出: {:name=>"Alice", :age=>30, :city=>"Wonderland", :country=>"Wonderland", :occupation=>"Developer"}
# 检查键是否存在puts hash.key?(:name) # 输出: trueputs hash.key?(:country) # 输出: false
# 检查值是否存在puts hash.value?("Alice") # 输出: trueputs hash.value?("Developer") # 输出: false
# 反转键值对puts hash.invert # 输出: {"Alice"=>:name, 30=>:age, "Wonderland"=>:city}
# 清空哈希hash.clearputs hash # 输出: {}
可以使用 each
方法遍历哈希中的键值对。
hash = { name: "Alice", age: 30, city: "Wonderland" }
hash.each do |key, value| puts "#{key}: #{value}"end
可以在创建哈希时指定默认值,当访问不存在的键时返回该默认值。
hash = Hash.new("Not Found")
puts hash[:name] # 输出: Not Found
# 可以为特定键设置默认值hash.default = "Unknown"puts hash[:age] # 输出: Unknown
哈希可以包含其他哈希,从而形成多维哈希。
multi_hash = { person1: { name: "Alice", age: 30 }, person2: { name: "Bob", age: 25 }}
puts multi_hash[:person1][:name] # 输出: Aliceputs multi_hash[:person2][:age] # 输出: 25
以下是一个综合示例,展示了哈希的创建、修改和常用方法:
# 创建哈希person = { name: "Alice", age: 30, city: "Wonderland" }
# 访问和修改元素puts person[:name] # 输出: Aliceperson[:age] = 31puts person[:age] # 输出: 31
# 添加新元素person[:country] = "Wonderland"puts person # 输出: {:name=>"Alice", :age=>31, :city=>"Wonderland", :country=>"Wonderland"}
# 删除元素person.delete(:city)puts person # 输出: {:name=>"Alice", :age=>31, :country=>"Wonderland"}
# 获取所有键和值puts person.keys # 输出: [:name, :age, :country]puts person.values # 输出: ["Alice", 31, "Wonderland"]
# 合并哈希person2 = { occupation: "Developer", hobby: "Reading" }puts person.merge(person2) # 输出: {:name=>"Alice", :age=>31, :country=>"Wonderland", :occupation=>"Developer", :hobby=>"Reading"}
# 迭代person.each do |key, value| puts "#{key}: #{value}"end
在 Ruby 中,条件语句用于根据不同的条件执行不同的代码块。以下是一些常见的条件语句,包括 if
、unless
、case
等。
if
语句用于在条件为真时执行代码块。
# 基本 if 语句if condition # 执行代码end
# 带有 else 的 if 语句if condition # 条件为真时执行else # 条件为假时执行end
# 带有 elsif 的 if 语句if condition1 # 条件1为真时执行elsif condition2 # 条件2为真时执行else # 条件都为假时执行end
age = 25
if age < 18 puts "You are a minor."elsif age >= 18 && age <= 65 puts "You are an adult."else puts "You are a senior."end
unless
语句
Section titled “unless 语句”unless
语句用于在条件为假时执行代码块。
# 基本 unless 语句unless condition # 条件为假时执行end
# 带有 else 的 unless 语句unless condition # 条件为假时执行else # 条件为真时执行end
status = "inactive"
unless status == "active" puts "The status is not active."else puts "The status is active."end
case
语句
Section titled “case 语句”case
语句用于基于不同的值执行不同的代码块,类似于其他语言中的 switch
语句。
# 基本 case 语句case expressionwhen value1 # 当 expression == value1 时执行when value2 # 当 expression == value2 时执行else # 当所有条件都不满足时执行end
grade = "B"
case gradewhen "A" puts "Excellent!"when "B" puts "Good!"when "C" puts "Fair!"when "D" puts "Poor!"else puts "Failing!"end
单行条件语句
Section titled “单行条件语句”Ruby 支持将条件语句写成单行形式,用于简单的条件判断。
if
单行形式
Section titled “if 单行形式”puts "You are an adult." if age >= 18
unless
单行形式
Section titled “unless 单行形式”puts "You are a minor." unless age >= 18
三元操作符是一种简洁的条件判断方式,类似于其他语言中的三元运算符 ?:
。
# 三元操作符condition ? expression_if_true : expression_if_false
age = 20status = age >= 18 ? "adult" : "minor"puts status # 输出: "adult"
可以使用逻辑运算符 &&
(与)、||
(或)和 !
(非)来组合条件。
age = 25country = "USA"
if age >= 18 && country == "USA" puts "You are eligible to vote in the USA."end
if age < 18 || country != "USA" puts "You are not eligible to vote."end
if !age.nil? puts "Age is provided."end
以下是一个综合示例,展示了各种条件语句的用法:
# if 语句age = 20if age >= 18 puts "You are an adult."else puts "You are a minor."end
# unless 语句status = "inactive"unless status == "active" puts "The status is not active."else puts "The status is active."end
# case 语句grade = "B"case gradewhen "A" puts "Excellent!"when "B" puts "Good!"when "C" puts "Fair!"when "D" puts "Poor!"else puts "Failing!"end
# 单行条件语句puts "You are an adult." if age >= 18puts "You are a minor." unless age >= 18
# 三元操作符status = age >= 18 ? "adult" : "minor"puts status # 输出: "adult"
# 逻辑运算符if age >= 18 && status == "adult" puts "You are eligible to vote."end
在 Ruby 中,循环用于重复执行一段代码,直到满足某个条件。以下是 Ruby 中常见的循环结构,包括 while
、until
、for
、each
等。
while
循环
Section titled “while 循环”while
循环在条件为真时重复执行代码块。
# 基本 while 循环while condition # 执行代码end
i = 0while i < 5 puts i i += 1end
until
循环
Section titled “until 循环”until
循环在条件为假时重复执行代码块。
# 基本 until 循环until condition # 执行代码end
i = 0until i >= 5 puts i i += 1end
for
循环
Section titled “for 循环”for
循环用于遍历一个范围或一个集合中的元素。
# 基本 for 循环for variable in collection # 执行代码end
for i in 0..4 puts iend
each
循环
Section titled “each 循环”each
方法用于遍历集合(如数组、哈希)中的元素。
# 数组的 each 循环array = [1, 2, 3, 4, 5]array.each do |element| puts elementend
# 哈希的 each 循环hash = { name: "Alice", age: 30, city: "Wonderland" }hash.each do |key, value| puts "#{key}: #{value}"end
times
循环
Section titled “times 循环”times
方法用于指定代码块执行的次数。
# 基本 times 循环n.times do # 执行代码end
5.times do |i| puts iend
loop
循环
Section titled “loop 循环”loop
方法用于创建一个无限循环,可以通过 break
语句退出循环。
loop do # 执行代码 break if conditionend
i = 0loop do puts i i += 1 break if i >= 5end
可以使用 break
、next
和 redo
控制循环的执行。
break
:退出循环next
:跳过当前迭代,进入下一次迭代redo
:重新执行当前迭代
# 使用 breaki = 0while i < 10 puts i i += 1 break if i == 5end
# 使用 next(0..10).each do |i| next if i % 2 == 0 puts iend
# 使用 redoi = 0while i < 5 puts i i += 1 redo if i == 3end
以下是一个综合示例,展示了各种循环的用法:
# while 循环i = 0while i < 5 puts "while: #{i}" i += 1end
# until 循环i = 0until i >= 5 puts "until: #{i}" i += 1end
# for 循环for i in 0..4 puts "for: #{i}"end
# each 循环array = [1, 2, 3, 4, 5]array.each do |element| puts "each: #{element}"end
# 哈希的 each 循环hash = { name: "Alice", age: 30, city: "Wonderland" }hash.each do |key, value| puts "hash each: #{key}: #{value}"end
# times 循环5.times do |i| puts "times: #{i}"end
# loop 循环i = 0loop do puts "loop: #{i}" i += 1 break if i >= 5end
# 循环控制示例# 使用 breaki = 0while i < 10 puts "break example: #{i}" i += 1 break if i == 5end
# 使用 next(0..10).each do |i| next if i % 2 == 0 puts "next example: #{i}"end
# 使用 redoi = 0while i < 5 puts "redo example: #{i}" i += 1 redo if i == 3end
do,redo
Section titled “do,redo”在 Ruby 中,do
关键字用于定义代码块,redo
关键字用于重新执行当前迭代。这两者在循环和代码块中有着重要的应用。以下是对 do
和 redo
的详细介绍及其用法。
do
关键字
Section titled “do 关键字”do
关键字用于定义一个代码块,通常与迭代方法(如 each
、times
等)或循环结构(如 while
、until
等)一起使用。代码块以 end
关键字结束。
# 使用 do...end 定义代码块5.times do |i| puts "This is iteration #{i}"end
# 使用 {} 定义单行代码块(等效于 do...end)5.times { |i| puts "This is iteration #{i}" }
# 与 each 方法一起使用[1, 2, 3].each do |num| puts num * 2end
# 与 while 循环一起使用i = 0while i < 3 do puts "i is #{i}" i += 1end
redo
关键字
Section titled “redo 关键字”redo
关键字用于重新执行当前的迭代,而不进行条件检查或移动到下一个迭代。它通常在迭代器或循环结构中使用,用于重新尝试当前的迭代。
# 使用 redo 重新执行当前迭代i = 0while i < 5 do puts "i is #{i}" i += 1 redo if i == 3 # 在 i 等于 3 时重新执行当前迭代end
在这个示例中,当 i
等于 3 时,redo
关键字会导致循环重新执行当前迭代,使得 i
再次等于 3,可能导致无限循环。为了避免这种情况,可以使用其他条件或计数器来控制 redo
的执行。
# 使用 redo 重新尝试输入有效的数字attempts = 0begin puts "Enter a number greater than 10:" num = gets.to_i attempts += 1 redo if num <= 10 && attempts < 3 # 重试最多三次rescue puts "Invalid input. Please try again." retryend
以下是一个综合示例,展示了 do
和 redo
的结合使用:
# 使用 do 和 redo 进行用户输入验证attempts = 0
3.times do puts "Enter a number greater than 10:" num = gets.to_i attempts += 1 if num > 10 puts "Thank you! You entered #{num}." break elsif attempts < 3 puts "Invalid number. Try again." redo # 重新尝试当前迭代 else puts "Too many invalid attempts." endend
按定义方式分类
Section titled “按定义方式分类”1. 实例方法
Section titled “1. 实例方法”实例方法是在类中定义的方法,可以由类的实例调用。
class Person def initialize(name, age) @name = name @age = age end
def introduce "Hi, I'm #{@name} and I'm #{@age} years old." endend
person = Person.new("Alice", 30)puts person.introduce # 输出: Hi, I'm Alice and I'm 30 years old.
2. 类方法
Section titled “2. 类方法”类方法是使用 self
关键字或类名定义的方法,可以直接由类调用。
class MathHelper def self.square(x) x * x end
# 或者 def MathHelper.cube(x) x * x * x endend
puts MathHelper.square(4) # 输出: 16puts MathHelper.cube(3) # 输出: 27
按参数类型分类
Section titled “按参数类型分类”1. 无参数方法
Section titled “1. 无参数方法”无参数方法不接受任何参数。
def greet "Hello!"end
puts greet # 输出: Hello!
2. 有参数方法
Section titled “2. 有参数方法”有参数方法接受一个或多个参数。
def add(a, b) a + bend
puts add(2, 3) # 输出: 5
3. 默认参数方法
Section titled “3. 默认参数方法”默认参数方法为参数提供默认值。
def greet(name = "stranger") "Hello, #{name}!"end
puts greet # 输出: Hello, stranger!puts greet("Alice") # 输出: Hello, Alice!
4. 可变参数方法
Section titled “4. 可变参数方法”可变参数方法可以接受不定数量的参数。
def sum(*numbers) numbers.reduce(0) { |sum, num| sum + num }end
puts sum(1, 2, 3) # 输出: 6puts sum(4, 5, 6, 7) # 输出: 22
按作用域分类
Section titled “按作用域分类”1. 私有方法
Section titled “1. 私有方法”私有方法只能在类的内部调用,不能被类的实例直接调用。使用 private
关键字定义。
class Person def initialize(name) @name = name end
def show_name display_name end
private
def display_name "Name: #{@name}" endend
person = Person.new("Alice")puts person.show_name # 输出: Name: Alice# puts person.display_name # 报错: private method `display_name' called
2. 保护方法
Section titled “2. 保护方法”保护方法只能在类的内部或子类中调用,不能被类的实例直接调用。使用 protected
关键字定义。
class Parent def initialize(name) @name = name end
protected
def display_name "Name: #{@name}" endend
class Child < Parent def show_name display_name endend
child = Child.new("Alice")puts child.show_name # 输出: Name: Alice# puts child.display_name # 报错: protected method `display_name' called
1. 访问器方法
Section titled “1. 访问器方法”访问器方法用于读取和设置实例变量的值。可以使用 attr_reader
、attr_writer
和 attr_accessor
自动生成访问器方法。
class Person attr_accessor :name, :age
def initialize(name, age) @name = name @age = age endend
person = Person.new("Alice", 30)puts person.name # 输出: Aliceperson.age = 31puts person.age # 输出: 31
2. 转换方法
Section titled “2. 转换方法”转换方法用于将对象转换为其他类型。常见的方法有 to_s
、to_i
、to_f
等。
class Person def initialize(name, age) @name = name @age = age end
def to_s "Name: #{@name}, Age: #{@age}" endend
person = Person.new("Alice", 30)puts person.to_s # 输出: Name: Alice, Age: 30
3. 操作方法
Section titled “3. 操作方法”操作方法执行特定的操作或计算。
class MathHelper def self.factorial(n) return 1 if n == 0 n * factorial(n - 1) endend
puts MathHelper.factorial(5) # 输出: 120
在 Ruby 中,代码块(Block)是将一组代码封装在一起并传递给方法的一种方式。代码块可以用于迭代、资源管理、延迟执行等场景。代码块可以使用 do...end
或 {}
定义,并且可以作为方法的参数传递。
使用 do...end
定义代码块
Section titled “使用 do...end 定义代码块”3.times do puts "Hello, Ruby!"end
使用 {}
定义代码块
Section titled “使用 {} 定义代码块”3.times { puts "Hello, Ruby!" }
代码块与方法
Section titled “代码块与方法”许多 Ruby 方法接受代码块作为参数,并在方法内部使用 yield
关键字来调用代码块。
示例:使用 yield
调用代码块
Section titled “示例:使用 yield 调用代码块”def greet puts "Hello!" yield if block_given? # 检查是否传递了代码块 puts "Goodbye!"end
greet { puts "How are you?" }
输出:
Hello!How are you?Goodbye!
示例:使用代码块传递参数
Section titled “示例:使用代码块传递参数”def greet yield("Alice") if block_given?end
greet { |name| puts "Hello, #{name}!" }
输出:
Hello, Alice!
代码块可以接受一个或多个参数,这些参数在块变量中指定。
示例:块变量
Section titled “示例:块变量”[1, 2, 3, 4, 5].each do |number| puts number * 2end
输出:
246810
Proc
和 Lambda
Section titled “Proc 和 Lambda”Proc
和 Lambda
是代码块的对象化形式,允许将代码块存储在变量中,并在以后调用。
创建 Proc
对象
Section titled “创建 Proc 对象”my_proc = Proc.new { |x| puts x * 2 }my_proc.call(5) # 输出: 10
创建 Lambda
对象
Section titled “创建 Lambda 对象”my_lambda = ->(x) { puts x * 2 }my_lambda.call(5) # 输出: 10
区别 Proc
和 Lambda
Section titled “区别 Proc 和 Lambda”Lambda
检查参数数量,Proc
不检查。Lambda
返回时从lambda
返回,Proc
返回时从方法返回。
def test_lambda my_lambda = -> { return "Lambda" } my_lambda.call "End of method"end
def test_proc my_proc = Proc.new { return "Proc" } my_proc.call "End of method"end
puts test_lambda # 输出: End of methodputs test_proc # 输出: Proc
yield
和 block_given?
Section titled “yield 和 block_given?”可以使用 yield
关键字在方法内部调用传递的代码块。使用 block_given?
可以检查是否提供了代码块。
示例:yield
和 block_given?
Section titled “示例:yield 和 block_given?”def display_message puts "Start of method" yield if block_given? puts "End of method"end
display_message { puts "Inside the block" }
输出:
Start of methodInside the blockEnd of method
以下是一个综合示例,展示了代码块、Proc
和 Lambda
的用法:
# 使用代码块进行迭代def custom_each(array) for element in array yield(element) endend
custom_each([1, 2, 3, 4, 5]) { |num| puts num * 2 }
# 使用 Proc 和 Lambdamy_proc = Proc.new { |x| puts "Proc: #{x * 2}" }my_lambda = ->(x) { puts "Lambda: #{x * 2}" }
[1, 2, 3].each(&my_proc)[1, 2, 3].each(&my_lambda)
# 方法中使用 yield 和 block_given?def execute_block if block_given? puts "Block is given!" yield else puts "No block provided." endend
execute_block { puts "Hello from block!" }execute_block
在 Ruby 中,类(Class)是面向对象编程的基础。类是对象的蓝图或模板,它定义了对象的属性(变量)和行为(方法)。以下是关于 Ruby 类的详细介绍,包括定义类、创建对象、实例变量和方法、类变量和方法、继承和模块等。
可以使用 class
关键字定义一个类。
class Person # 类的内容end
使用 new
方法创建类的实例(对象)。
class Person def initialize(name, age) @name = name @age = age end
def display_info "Name: #{@name}, Age: #{@age}" endend
person = Person.new("Alice", 30)puts person.display_info # 输出: Name: Alice, Age: 30
实例变量和方法
Section titled “实例变量和方法”实例变量以 @
开头,用于存储对象的属性。实例方法用于定义对象的行为。
class Person def initialize(name, age) @name = name @age = age end
def display_info "Name: #{@name}, Age: #{@age}" endend
可以使用 attr_reader
、attr_writer
和 attr_accessor
自动生成访问器方法。
class Person attr_accessor :name, :age
def initialize(name, age) @name = name @age = age endend
person = Person.new("Alice", 30)puts person.name # 输出: Aliceperson.age = 31puts person.age # 输出: 31
类变量和方法
Section titled “类变量和方法”类变量以 @@
开头,类方法使用 self
或类名定义。
class Person @@count = 0
def initialize(name, age) @name = name @age = age @@count += 1 end
def self.count @@count endend
person1 = Person.new("Alice", 30)person2 = Person.new("Bob", 25)puts Person.count # 输出: 2
使用 <
关键字实现继承,子类可以继承父类的属性和方法。
class Person def initialize(name, age) @name = name @age = age end
def display_info "Name: #{@name}, Age: #{@age}" endend
class Student < Person def initialize(name, age, grade) super(name, age) @grade = grade end
def display_info "#{super}, Grade: #{@grade}" endend
student = Student.new("Charlie", 20, "A")puts student.display_info # 输出: Name: Charlie, Age: 20, Grade: A
模块用于组织方法和常量,可以作为命名空间或混入类中以增加功能。
module Greetable def greet "Hello!" endend
class Person include Greetable
def initialize(name) @name = name end
def display_name "Name: #{@name}" endend
person = Person.new("Alice")puts person.greet # 输出: Hello!puts person.display_name # 输出: Name: Alice
以下是一个综合示例,展示了类的定义、实例变量和方法、类变量和方法、继承和模块的使用:
# 模块定义module Describable def describe "This is a #{self.class.name}." endend
# 父类定义class Person include Describable # 混入模块
attr_accessor :name, :age @@count = 0
def initialize(name, age) @name = name @age = age @@count += 1 end
def display_info "Name: #{@name}, Age: #{@age}" end
def self.count @@count endend
# 子类定义class Student < Person attr_accessor :grade
def initialize(name, age, grade) super(name, age) @grade = grade end
def display_info "#{super}, Grade: #{@grade}" endend
# 创建对象并调用方法person = Person.new("Alice", 30)student = Student.new("Charlie", 20, "A")
puts person.display_info # 输出: Name: Alice, Age: 30puts person.describe # 输出: This is a Person.puts Student.count # 输出: 2puts student.display_info # 输出: Name: Charlie, Age: 20, Grade: Aputs student.describe # 输出: This is a Student.
在 Ruby 中,异常处理用于处理程序执行过程中可能发生的错误或异常情况。通过使用异常处理机制,可以在捕获异常时执行特定的代码,而不让程序崩溃。Ruby 提供了 begin-rescue-end
块、ensure
块、else
块和自定义异常等功能来实现异常处理。
基本异常处理
Section titled “基本异常处理”begin-rescue-end
块
Section titled “begin-rescue-end 块”使用 begin-rescue-end
块来捕获和处理异常。
begin # 可能引发异常的代码 result = 10 / 0rescue ZeroDivisionError => e # 处理 ZeroDivisionError 异常 puts "Error: #{e.message}"end
begin result = 10 / 0rescue ZeroDivisionError => e puts "Cannot divide by zero: #{e.message}"end
ensure
块
Section titled “ensure 块”ensure
块中的代码无论是否发生异常都会执行,通常用于清理资源或执行收尾工作。
begin # 可能引发异常的代码 result = 10 / 0rescue ZeroDivisionError => e puts "Error: #{e.message}"ensure puts "This will always be executed."end
else
块
Section titled “else 块”else
块中的代码在没有发生异常时执行。
begin # 可能引发异常的代码 result = 10 / 2rescue ZeroDivisionError => e puts "Error: #{e.message}"else puts "No errors occurred. Result is #{result}"ensure puts "This will always be executed."end
可以定义自定义异常类,通过继承 StandardError
类来实现。
class CustomError < StandardErrorend
def risky_method raise CustomError, "Something went wrong!"end
begin risky_methodrescue CustomError => e puts "Caught a custom error: #{e.message}"end
多个 rescue
子句
Section titled “多个 rescue 子句”可以在 begin-rescue-end
块中使用多个 rescue
子句来捕获不同类型的异常。
begin # 可能引发异常的代码 result = 10 / 0rescue ZeroDivisionError => e puts "ZeroDivisionError: #{e.message}"rescue StandardError => e puts "StandardError: #{e.message}"end
可以使用 retry
关键字在捕获异常后重新执行 begin
块。
attempts = 0
begin attempts += 1 puts "Attempt #{attempts}" result = 10 / 0rescue ZeroDivisionError => e puts "Error: #{e.message}" retry if attempts < 3ensure puts "This will always be executed."end
以下是一个综合示例,展示了各种异常处理的用法:
class CustomError < StandardErrorend
def divide(a, b) raise CustomError, "Custom error: b cannot be zero!" if b == 0 a / bend
begin puts "Result: #{divide(10, 2)}" puts "Result: #{divide(10, 0)}"rescue CustomError => e puts "Caught a custom error: #{e.message}"rescue ZeroDivisionError => e puts "Caught a division error: #{e.message}"else puts "No errors occurred."ensure puts "This will always be executed."end
Ruby 的标准库(Standard Library)包含了大量有用的类和模块,用于各种常见的编程任务。标准库随 Ruby 一起分发,无需额外安装。以下是一些常用的标准库及其功能简介和示例代码。
1. File
和 Dir
Section titled “1. File 和 Dir”用于文件和目录操作。
# 读取文件内容content = File.read("example.txt")puts content
# 写入文件内容File.write("example.txt", "Hello, Ruby!")
# 列出目录中的文件Dir.entries(".").each do |entry| puts entryend
2. JSON
Section titled “2. JSON”用于处理 JSON 数据。
require 'json'
# 将哈希转换为 JSON 字符串hash = { name: "Alice", age: 30 }json_str = JSON.generate(hash)puts json_str # 输出: {"name":"Alice","age":30}
# 将 JSON 字符串转换为哈希parsed_hash = JSON.parse(json_str)puts parsed_hash["name"] # 输出: Alice
3. Net::HTTP
Section titled “3. Net::HTTP”用于进行 HTTP 请求。
require 'net/http'require 'uri'
uri = URI("http://example.com")response = Net::HTTP.get(uri)puts response
4. Time
和 Date
Section titled “4. Time 和 Date”用于处理日期和时间。
require 'time'require 'date'
# 获取当前时间current_time = Time.nowputs current_time
# 解析时间字符串parsed_time = Time.parse("2023-08-07 12:34:56")puts parsed_time
# 创建日期对象date = Date.new(2023, 8, 7)puts date
# 日期计算next_week = date + 7puts next_week
5. Set
Section titled “5. Set”用于存储不重复的元素集合。
require 'set'
# 创建一个集合set = Set.new([1, 2, 3, 4, 5])puts set.include?(3) # 输出: true
# 添加和删除元素set.add(6)set.delete(2)puts set.to_a # 输出: [1, 3, 4, 5, 6]
6. Math
Section titled “6. Math”提供基本的数学方法和常量。
# 计算平方根puts Math.sqrt(16) # 输出: 4.0
# 计算三角函数puts Math.sin(Math::PI / 2) # 输出: 1.0
7. Digest
Section titled “7. Digest”用于计算字符串的哈希值。
require 'digest'
# 计算 MD5 哈希md5 = Digest::MD5.hexdigest("Hello, world!")puts md5 # 输出: fc3ff98e8c6a0d3087d515c0473f8677
# 计算 SHA256 哈希sha256 = Digest::SHA256.hexdigest("Hello, world!")puts sha256 # 输出: 64ec88ca00b268e5ba1a35678a1b5316d212f4f36631a3f62de1fac2016a4c41
8. OpenURI
Section titled “8. OpenURI”用于简化打开 URI 的操作,通常用于下载文件或读取网络资源。
require 'open-uri'
# 从 URL 读取内容content = URI.open("http://example.com").readputs content
9. ERB
Section titled “9. ERB”用于嵌入 Ruby 代码到文本中,通常用于生成动态内容。
require 'erb'
# 定义模板template = "Hello, <%= name %>!"name = "Alice"
# 渲染模板erb = ERB.new(template)result = erb.result(binding)puts result # 输出: Hello, Alice!
10. CSV
Section titled “10. CSV”用于处理 CSV 文件。
require 'csv'
# 读取 CSV 文件CSV.foreach("example.csv") do |row| puts row.inspectend
# 写入 CSV 文件CSV.open("example.csv", "wb") do |csv| csv << ["Name", "Age", "City"] csv << ["Alice", 30, "Wonderland"]end
以下是一个综合示例,展示了如何使用多个标准库来完成一些常见任务:
require 'json'require 'net/http'require 'uri'require 'digest'require 'csv'
# 下载 JSON 数据uri = URI("https://jsonplaceholder.typicode.com/posts")response = Net::HTTP.get(uri)posts = JSON.parse(response)
# 处理数据并计算哈希值posts.each do |post| title = post["title"] body = post["body"] hash = Digest::SHA256.hexdigest(body)
puts "Title: #{title}" puts "Body: #{body}" puts "Hash: #{hash}" puts "-" * 40end
# 保存数据到 CSV 文件CSV.open("posts.csv", "wb") do |csv| csv << ["ID", "Title", "Body", "Hash"] posts.each do |post| title = post["title"] body = post["body"] hash = Digest::SHA256.hexdigest(body) csv << [post["id"], title, body, hash] endend