MK
摩柯社区 - 一个极简的技术知识社区
AI 面试

Ruby 基础语法全面解析

2022-12-074.9k 阅读

变量与数据类型

变量

在 Ruby 中,变量的命名遵循一定规则。变量名以字母或下划线开头,后续字符可以是字母、数字或下划线。变量名区分大小写。

Ruby 有几种不同类型的变量:

  1. 局部变量:以小写字母或下划线开头。例如:
name = "John"
_age = 30

局部变量的作用域通常是定义它的方法、块或循环内。一旦超出这个范围,变量就无法访问。

  1. 实例变量:以 @ 符号开头。实例变量主要用于类的实例中,不同实例的实例变量相互独立。
class Person
  def initialize(name)
    @name = name
  end

  def show_name
    puts @name
  end
end

person1 = Person.new("Alice")
person1.show_name

在上述代码中,@namePerson 类的实例变量,每个 Person 实例都有自己的 @name 副本。

  1. 类变量:以 @@ 符号开头。类变量在类的所有实例之间共享。
class Counter
  @@count = 0

  def initialize
    @@count += 1
  end

  def self.show_count
    puts @@count
  end
end

counter1 = Counter.new
counter2 = Counter.new
Counter.show_count

这里 @@countCounter 类的类变量,无论创建多少个 Counter 实例,@@count 都是共享的。

  1. 全局变量:以 $ 符号开头。全局变量在整个程序中都可访问,但过度使用全局变量可能导致代码难以维护,因为任何部分的代码都可以修改它。
$global_variable = "This is a global variable"
puts $global_variable

数据类型

  1. 整数:Ruby 支持不同进制的整数表示。十进制是默认的,也可以使用十六进制(以 0x 开头)、八进制(以 0 开头)和二进制(以 0b 开头)。
decimal_num = 10
hex_num = 0x10  # 十六进制,等于十进制的16
octal_num = 010  # 八进制,等于十进制的8
binary_num = 0b10  # 二进制,等于十进制的2

整数可以进行常见的算术运算,如加法、减法、乘法和除法。

a = 5
b = 3
puts a + b  # 输出8
puts a - b  # 输出2
puts a * b  # 输出15
puts a / b  # 输出1,因为是整数除法,结果会截断小数部分
puts a % b  # 输出2,取模运算
  1. 浮点数:用于表示带有小数部分的数字。
float_num1 = 3.14
float_num2 = 1.5e2  # 科学计数法,等于150.0

浮点数运算与整数运算类似,但需要注意浮点数精度问题。

a = 0.1
b = 0.2
puts a + b  # 理论上应是0.3,但实际输出可能接近0.30000000000000004,这是浮点数精度问题
  1. 字符串:在 Ruby 中,字符串是不可变对象。可以使用单引号或双引号创建字符串。
single_quoted_string = 'This is a single - quoted string'
double_quoted_string = "This is a double - quoted string"

双引号字符串支持字符串插值,即可以在字符串中嵌入变量。

name = "Ruby"
message = "Hello, #{name}!"
puts message  # 输出Hello, Ruby!

字符串有许多实用的方法,如 length 获取字符串长度,upcase 转换为大写,downcase 转换为小写等。

str = "ruby programming"
puts str.length  # 输出15
puts str.upcase  # 输出RUBY PROGRAMMING
puts str.downcase  # 输出ruby programming
  1. 布尔值:Ruby 中有两个布尔值:truefalse。布尔值常用于条件判断。
is_true = true
is_false = false
if is_true
  puts "This is true"
else
  puts "This is false"
end
  1. 数组:数组是有序的对象集合,可以包含不同类型的元素。
array1 = [1, "two", true]
array2 = Array.new(3, "default")  # 创建一个包含3个"default"的数组

可以通过索引访问数组元素,索引从 0 开始。

array = [10, 20, 30]
puts array[0]  # 输出10
puts array[1]  # 输出20

数组有很多有用的方法,如 push 向数组末尾添加元素,pop 从数组末尾移除元素,join 将数组元素连接成字符串等。

array = [1, 2, 3]
array.push(4)
puts array  # 输出[1, 2, 3, 4]
array.pop
puts array  # 输出[1, 2, 3]
str = array.join(', ')
puts str  # 输出1, 2, 3
  1. 哈希:哈希是键值对的集合,其中键是唯一的。
hash1 = {name: "Ruby", version: 2.7}
hash2 = Hash.new("default value")  # 创建一个默认值为"default value"的哈希

可以通过键来访问哈希的值。

hash = {city: "New York", country: "USA"}
puts hash[:city]  # 输出New York

哈希也有许多方法,如 keys 获取所有键,values 获取所有值,each 遍历哈希的键值对等。

hash = {a: 1, b: 2}
hash.each do |key, value|
  puts "#{key}: #{value}"
end

运算符

算术运算符

  1. 加法(+:用于两个数相加。
a = 5
b = 3
sum = a + b
puts sum  # 输出8
  1. 减法(-:用于两个数相减。
a = 5
b = 3
difference = a - b
puts difference  # 输出2
  1. 乘法(*:用于两个数相乘。
a = 5
b = 3
product = a * b
puts product  # 输出15
  1. 除法(/:整数除法会截断小数部分,如果需要得到浮点数结果,至少有一个操作数应为浮点数。
a = 5
b = 3
integer_division = a / b
puts integer_division  # 输出1
float_division = a.to_f / b
puts float_division  # 输出1.6666666666666667
  1. 取模(%:返回除法的余数。
a = 5
b = 3
modulo = a % b
puts modulo  # 输出2
  1. 幂运算(**:计算一个数的指定次幂。
a = 2
b = 3
power = a ** b
puts power  # 输出8

比较运算符

  1. 等于(==:比较两个值是否相等。
a = 5
b = 5
puts a == b  # 输出true
  1. 不等于(!=:比较两个值是否不相等。
a = 5
b = 3
puts a != b  # 输出true
  1. 大于(>:比较左边的值是否大于右边的值。
a = 5
b = 3
puts a > b  # 输出true
  1. 小于(<:比较左边的值是否小于右边的值。
a = 3
b = 5
puts a < b  # 输出true
  1. 大于等于(>=:比较左边的值是否大于或等于右边的值。
a = 5
b = 5
puts a >= b  # 输出true
  1. 小于等于(<=:比较左边的值是否小于或等于右边的值。
a = 5
b = 5
puts a <= b  # 输出true

逻辑运算符

  1. 逻辑与(&&:只有当两个操作数都为 true 时,结果才为 true
a = true
b = false
puts a && b  # 输出false
  1. 逻辑或(||:只要有一个操作数为 true,结果就为 true
a = true
b = false
puts a || b  # 输出true
  1. 逻辑非(!:对操作数进行取反,true 变为 falsefalse 变为 true
a = true
puts!a  # 输出false

赋值运算符

  1. 简单赋值(=:将右边的值赋给左边的变量。
a = 5
  1. 复合赋值运算符:如 +=-=*=/=%= 等。
a = 5
a += 3  # 等同于 a = a + 3
puts a  # 输出8

其他运算符

  1. 范围运算符(....... 表示包含两端的范围,... 表示不包含右端点的范围。
range1 = 1..5  # 包含1到5
range2 = 1...5  # 包含1到4

范围可以用于循环等场景。

(1..5).each do |num|
  puts num
end
  1. 三元运算符(? ::是一种简洁的条件判断表达式。
a = 5
result = a > 3? "Greater" : "Less"
puts result  # 输出Greater

控制结构

if - else 语句

if - else 语句用于根据条件执行不同的代码块。

age = 20
if age >= 18
  puts "You are an adult"
else
  puts "You are a minor"
end

还可以使用 elsif 处理多个条件。

score = 85
if score >= 90
  puts "A"
elsif score >= 80
  puts "B"
elsif score >= 70
  puts "C"
else
  puts "D"
end

case 语句

case 语句用于根据不同的值执行不同的代码块,类似于其他语言中的 switch - case

day = "Monday"
case day
when "Monday"
  puts "Start of the week"
when "Friday"
  puts "Nearing the weekend"
else
  puts "Another day"
end

case 语句也可以用于比较范围等。

number = 5
case number
when 1..3
  puts "Small number"
when 4..6
  puts "Medium number"
else
  puts "Large number"
end

循环结构

  1. while 循环:只要条件为 true,就会重复执行代码块。
i = 0
while i < 5
  puts i
  i += 1
end
  1. until 循环:与 while 循环相反,只要条件为 false,就会重复执行代码块。
i = 0
until i >= 5
  puts i
  i += 1
end
  1. for 循环:用于遍历数组、范围等。
array = [1, 2, 3]
for num in array
  puts num
end
  1. each 方法:许多可枚举对象(如数组、哈希)都有 each 方法,用于遍历其中的元素。
array = [1, 2, 3]
array.each do |num|
  puts num
end

hash = {a: 1, b: 2}
hash.each do |key, value|
  puts "#{key}: #{value}"
end

方法定义与调用

方法定义

在 Ruby 中,使用 def 关键字定义方法。

def greet(name)
  puts "Hello, #{name}!"
end

上述代码定义了一个名为 greet 的方法,它接受一个参数 name,并输出问候语。

方法可以有默认参数。

def greet(name = "Guest")
  puts "Hello, #{name}!"
end

这样,在调用 greet 方法时,如果不传递参数,会使用默认值 "Guest"

方法调用

方法调用非常简单,只需使用方法名并传递必要的参数。

def add(a, b)
  a + b
end

result = add(3, 5)
puts result  # 输出8

如果方法没有参数,调用时可以省略括号。

def say_hello
  puts "Hello"
end

say_hello

类与对象

类的定义

使用 class 关键字定义类。

class Dog
  def initialize(name, breed)
    @name = name
    @breed = breed
  end

  def bark
    puts "#{@name} says Woof!"
  end
end

在上述代码中,Dog 类有一个构造方法 initialize,用于初始化对象的属性 @name@breed,还有一个 bark 方法用于让狗叫。

对象的创建与使用

通过调用类的构造方法来创建对象。

dog1 = Dog.new("Buddy", "Golden Retriever")
dog1.bark

这里创建了一个 Dog 类的实例 dog1,并调用了它的 bark 方法。

继承

Ruby 支持类的继承,使用 < 符号表示继承关系。

class Bulldog < Dog
  def snore
    puts "#{@name} is snoring"
  end
end

Bulldog 类继承自 Dog 类,它继承了 Dog 类的所有方法和属性,并且还可以定义自己特有的方法,如 snore

bulldog1 = Bulldog.new("Max", "Bulldog")
bulldog1.bark
bulldog1.snore

模块

模块定义

模块使用 module 关键字定义。模块主要用于将相关的方法和常量组织在一起,避免命名冲突。

module MathUtils
  PI = 3.14159

  def self.add(a, b)
    a + b
  end

  def self.multiply(a, b)
    a * b
  end
end

上述 MathUtils 模块定义了一个常量 PI 和两个类方法 addmultiply

模块的使用

可以通过模块名来访问模块中的方法和常量。

puts MathUtils::PI
result = MathUtils.add(3, 5)
puts result

模块还可以通过 include 关键字混入到类中,使类具有模块中的实例方法。

class Shape
  include MathUtils

  def area(radius)
    multiply(PI, radius ** 2)
  end
end

circle = Shape.new
puts circle.area(5)

异常处理

异常的抛出与捕获

在 Ruby 中,可以使用 raise 关键字抛出异常。

def divide(a, b)
  if b == 0
    raise ZeroDivisionError, "Cannot divide by zero"
  end
  a / b
end

上述 divide 方法在除数为 0 时抛出 ZeroDivisionError 异常。

使用 begin - rescue 块来捕获异常。

begin
  result = divide(10, 0)
rescue ZeroDivisionError => e
  puts "Error: #{e.message}"
end

这里捕获了 ZeroDivisionError 异常,并输出异常信息。

自定义异常

可以通过继承 StandardError 类来定义自己的异常。

class MyCustomError < StandardError
end

def some_method
  raise MyCustomError, "This is a custom error"
end

begin
  some_method
rescue MyCustomError => e
  puts "Caught custom error: #{e.message}"
end

块与迭代器

块是一段未命名的代码,用花括号 {}do...end 包围。

(1..5).each { |num| puts num }

上述代码中,{ |num| puts num } 就是一个块,它会对 (1..5) 中的每个数字执行 puts num 操作。

迭代器

迭代器是一个方法,它会对集合中的每个元素执行给定的块。除了 each 外,还有许多其他迭代器,如 mapselect 等。

  1. map 迭代器:对集合中的每个元素应用给定的块,并返回一个新的集合。
array = [1, 2, 3]
new_array = array.map { |num| num * 2 }
puts new_array  # 输出[2, 4, 6]
  1. select 迭代器:选择集合中满足给定块条件的元素,并返回一个新的集合。
array = [1, 2, 3, 4, 5]
even_numbers = array.select { |num| num.even? }
puts even_numbers  # 输出[2, 4]

文件操作

文件读取

使用 File.read 方法可以读取整个文件内容。

content = File.read('example.txt')
puts content

也可以逐行读取文件。

File.foreach('example.txt') do |line|
  puts line
end

文件写入

使用 File.write 方法可以写入文件,如果文件不存在会创建文件。

File.write('output.txt', "This is some text")

如果要追加内容到文件,可以使用 File.open 并指定 'a' 模式。

File.open('output.txt', 'a') do |file|
  file.puts "This is additional text"
end

正则表达式

正则表达式基础

在 Ruby 中,正则表达式使用 /pattern/ 形式定义。例如,匹配字符串中的数字:

string = "There are 10 apples"
match = string.match(/\d+/)
puts match.to_s  # 输出10

这里 /\d+/ 是一个正则表达式,\d 表示匹配任意数字,+ 表示匹配前面的字符一次或多次。

正则表达式方法

字符串有许多与正则表达式相关的方法,如 matchgsub 等。

  1. match 方法:尝试在字符串中匹配正则表达式,返回匹配结果。
string = "Hello, World!"
match = string.match(/Hello/)
puts match.to_s  # 输出Hello
  1. gsub 方法:全局替换字符串中匹配正则表达式的部分。
string = "aabbcc"
new_string = string.gsub(/a/, 'x')
puts new_string  # 输出xxbbcc

通过以上对 Ruby 基础语法的全面解析,希望能帮助你深入理解和掌握 Ruby 语言,为进一步的编程实践和项目开发打下坚实基础。在实际应用中,还需要不断练习和积累经验,以更好地发挥 Ruby 的强大功能。