Skip to content

Ruby 运算符

运算符是执行特定操作的符号或关键字。Ruby提供了丰富的运算符集合,使代码更加简洁和表达力强。本章将详细介绍Ruby中的各种运算符及其使用方法。

🎯 运算符概述

Ruby中的运算符可以分为以下几类:

  1. 算术运算符 - 执行数学运算
  2. 比较运算符 - 比较值的大小关系
  3. 逻辑运算符 - 执行布尔逻辑运算
  4. 赋值运算符 - 给变量赋值
  5. 位运算符 - 执行位级操作
  6. 范围运算符 - 创建范围对象
  7. 其他运算符 - 特殊用途的运算符

➕ 算术运算符

基本算术运算符

ruby
# 加法
puts 10 + 5        # 15
puts "Hello" + " " + "World"  # Hello World

# 减法
puts 10 - 5        # 5

# 乘法
puts 10 * 5        # 50
puts "Ruby" * 3    # RubyRubyRuby

# 除法
puts 10 / 5        # 2
puts 10 / 3        # 3 (整数除法)
puts 10.0 / 3      # 3.3333333333333335 (浮点数除法)

# 取模(求余数)
puts 10 % 3        # 1
puts 10.5 % 3      # 1.5

# 幂运算
puts 2 ** 3        # 8
puts 9 ** 0.5      # 3.0 (平方根)

一元运算符

ruby
# 正号
puts +5            # 5

# 负号
puts -5            # -5
puts -(-5)         # 5

# 自增自减(Ruby没有++和--运算符)
counter = 5
counter += 1       # 等同于 counter = counter + 1
puts counter       # 6

counter -= 1       # 等同于 counter = counter - 1
puts counter       # 5

🔄 比较运算符

基本比较运算符

ruby
# 相等性比较
puts 5 == 5        # true
puts 5 == "5"      # false (类型不同)
puts 5.eql?("5")   # false (严格相等)
puts 5 === 5       # true (case语句中的相等)

# 不等性比较
puts 5 != 3        # true
puts 5 != 5        # false

# 大小比较
puts 5 > 3         # true
puts 5 < 3         # false
puts 5 >= 5        # true
puts 5 <= 3        # false

# 字符串比较
puts "apple" < "banana"    # true (按字典序)
puts "Apple" < "apple"     # true (大写字母ASCII值更小)

特殊比较运算符

ruby
# 安全比较运算符 <=>
result = 5 <=> 3   # 1 (左边大于右边)
result = 5 <=> 5   # 0 (相等)
result = 3 <=> 5   # -1 (左边小于右边)

# 在范围检查中的应用
case 75
when 90..100
  puts "优秀"
when 80...90
  puts "良好"
when 60...80
  puts "及格"
else
  puts "不及格"
end
# 输出: 及格

对象比较

ruby
# equal? - 检查是否是同一个对象
a = "hello"
b = "hello"
c = a

puts a.equal?(b)   # false (不同的对象)
puts a.equal?(c)   # true (同一个对象)

# == - 检查值是否相等
puts a == b        # true (值相等)

# eql? - 检查值和类型是否都相等
puts 1 == 1.0      # true
puts 1.eql?(1.0)   # false (类型不同)

🔣 逻辑运算符

布尔逻辑运算符

ruby
# 与运算 (and, &&)
puts true && true     # true
puts true && false    # false
puts false && true    # false
puts false && false   # false

# 或运算 (or, ||)
puts true || true     # true
puts true || false    # true
puts false || true    # true
puts false || false   # false

# 非运算 (not, !)
puts !true            # false
puts !false           # true
puts !!true           # true (双重否定)

优先级差异

ruby
# && 和 || 的优先级高于 and 和 or
result1 = true || false and false
puts result1          # true (等同于 (true || false) and false)

result2 = true or false and false
puts result2          # false (等同于 true or (false and false))

# 推荐使用 && 和 || 以避免混淆

短路求值

ruby
# && 短路:如果左边为false,不计算右边
def expensive_operation
  puts "执行昂贵操作"
  true
end

false && expensive_operation  # 不会输出"执行昂贵操作"

# || 短路:如果左边为true,不计算右边
true || expensive_operation   # 不会输出"执行昂贵操作"

# 利用短路求值设置默认值
name = nil
display_name = name || "匿名用户"
puts display_name             # 匿名用户

# 安全导航
user = nil
user_name = user&.name || "默认名称"
puts user_name                # 默认名称

📝 赋值运算符

基本赋值运算符

ruby
# 简单赋值
x = 10
puts x            # 10

# 复合赋值运算符
x += 5            # 等同于 x = x + 5
puts x            # 15

x -= 3            # 等同于 x = x - 3
puts x            # 12

x *= 2            # 等同于 x = x * 2
puts x            # 24

x /= 4            # 等同于 x = x / 4
puts x            # 6

x %= 5            # 等同于 x = x % 5
puts x            # 1

x **= 3           # 等同于 x = x ** 3
puts x            # 1

并行赋值

ruby
# 基本并行赋值
a, b = 1, 2
puts "a = #{a}, b = #{b}"  # a = 1, b = 2

# 交换变量值
a, b = b, a
puts "a = #{a}, b = #{b}"  # a = 2, b = 1

# 数组解构
first, *rest = [1, 2, 3, 4, 5]
puts "first = #{first}"    # first = 1
puts "rest = #{rest}"      # rest = [2, 3, 4, 5]

# 忽略某些值
_, second, _ = [10, 20, 30]
puts "second = #{second}"  # second = 20

条件赋值运算符

ruby
# ||= 条件赋值(仅当变量为nil或false时赋值)
name = nil
name ||= "默认名称"
puts name          # 默认名称

name ||= "新名称"
puts name          # 默认名称 (不会改变)

# &&= 条件赋值(仅当变量为真时赋值)
value = 10
value &&= value * 2
puts value         # 20

value = nil
value &&= value * 2
puts value         # nil

🔢 位运算符

基本位运算符

ruby
# 按位与 (&)
puts 5 & 3         # 1 (101 & 011 = 001)

# 按位或 (|)
puts 5 | 3         # 7 (101 | 011 = 111)

# 按位异或 (^)
puts 5 ^ 3         # 6 (101 ^ 011 = 110)

# 按位取反 (~)
puts ~5            # -6 (二进制补码)

# 左移 (<<)
puts 5 << 1        # 10 (101 << 1 = 1010)
puts 5 << 2        # 20 (101 << 2 = 10100)

# 右移 (>>)
puts 20 >> 1       # 10 (10100 >> 1 = 1010)
puts 20 >> 2       # 5 (10100 >> 2 = 101)

位运算应用示例

ruby
# 权限检查示例
class Permissions
  READ = 1 << 0      # 1 (001)
  WRITE = 1 << 1     # 2 (010)
  EXECUTE = 1 << 2   # 4 (100)
  
  def initialize(permissions = 0)
    @permissions = permissions
  end
  
  def grant(permission)
    @permissions |= permission
  end
  
  def revoke(permission)
    @permissions &= ~permission
  end
  
  def has_permission?(permission)
    (@permissions & permission) != 0
  end
  
  def permissions
    perms = []
    perms << "读取" if has_permission?(READ)
    perms << "写入" if has_permission?(WRITE)
    perms << "执行" if has_permission?(EXECUTE)
    perms.empty? ? "无权限" : perms.join(", ")
  end
end

# 使用权限系统
user_perms = Permissions.new
puts user_perms.permissions  # 无权限

user_perms.grant(Permissions::READ)
user_perms.grant(Permissions::WRITE)
puts user_perms.permissions  # 读取, 写入

user_perms.revoke(Permissions::WRITE)
puts user_perms.permissions  # 读取

📏 范围运算符

范围创建

ruby
# 包含结束值的范围 (..)
inclusive_range = 1..5
puts inclusive_range.include?(5)  # true
puts inclusive_range.to_a         # [1, 2, 3, 4, 5]

# 不包含结束值的范围 (...)
exclusive_range = 1...5
puts exclusive_range.include?(5)  # false
puts exclusive_range.to_a         # [1, 2, 3, 4]

# 字符范围
letter_range = 'a'..'e'
puts letter_range.to_a.join(',')  # a,b,c,d,e

范围应用

ruby
# 在case语句中使用范围
def grade(score)
  case score
  when 90..100
    "优秀"
  when 80...90
    "良好"
  when 70...80
    "中等"
  when 60...70
    "及格"
  else
    "不及格"
  end
end

puts grade(95)  # 优秀
puts grade(85)  # 良好
puts grade(75)  # 中等

# 范围迭代
(1..5).each { |n| print "#{n} " }  # 1 2 3 4 5
puts

('a'..'e').each { |c| print "#{c} " }  # a b c d e
puts

🎯 其他运算符

方法调用运算符

ruby
# 点运算符 (.)
class Calculator
  def add(a, b)
    a + b
  end
end

calc = Calculator.new
result = calc.add(2, 3)
puts result  # 5

# 安全导航运算符 (&.)
user = nil
name_length = user&.name&.length  # 不会引发NoMethodError
puts name_length  # nil

数组和哈希访问运算符

ruby
# 数组访问
arr = [1, 2, 3, 4, 5]
puts arr[0]        # 1
puts arr[-1]       # 5
puts arr[1..3]     # [2, 3, 4]

# 哈希访问
hash = {name: "张三", age: 25}
puts hash[:name]   # 张三
puts hash["name"]  # nil (键不存在)

# 默认值访问
scores = Hash.new(0)
scores[:math] = 95
puts scores[:english]  # 0 (默认值)

正则表达式运算符

ruby
# 匹配运算符 (=~)
text = "Hello, Ruby!"
puts text =~ /Ruby/    # 7 (匹配位置)
puts text =~ /python/  # nil (不匹配)

# 不匹配运算符 (!~)
puts text !~ /Ruby/    # false
puts text !~ /python/  # true

# 匹配数据访问
if match_data = "2023-12-25".match(/(\d{4})-(\d{2})-(\d{2})/)
  year, month, day = match_data[1], match_data[2], match_data[3]
  puts "年: #{year}, 月: #{month}, 日: #{day}"  # 年: 2023, 月: 12, 日: 25
end

⚖️ 运算符优先级

优先级列表(从高到低)

ruby
# 1.  ! ~ + - (一元运算符)
# 2.  ** (幂运算)
# 3.  * / % (乘除模)
# 4.  + - (加减)
# 5.  << >> (位移)
# 6.  & (按位与)
# 7.  | ^ (按位或、异或)
# 8.  > >= < <= (比较)
# 9.  <=> == === != =~ !~ (相等性)
# 10. && (逻辑与)
# 11. || (逻辑或)
# 12. .. ... (范围)
# 13. ? : (三元运算符)
# 14. = += -= *= /= %= **= &= |= ^= <<= >>= (赋值)
# 15. not (逻辑非)
# 16. and or (逻辑运算)

# 示例:理解优先级
result = 2 + 3 * 4     # 14 (乘法优先级高于加法)
result = (2 + 3) * 4   # 20 (括号改变优先级)

result = true || false && false  # true (&&优先级高于||)
result = true or false and false # false (and/or优先级低于||)

使用括号明确意图

ruby
# 好的做法:使用括号明确运算顺序
average = (score1 + score2 + score3) / 3
is_valid = (user.active? && user.verified?) || admin?
result = (base_value * multiplier) + adjustment

# 避免依赖运算符优先级的记忆
# bad: is_adult = age >= 18 && has_id && !is_banned
# good: is_adult = (age >= 18) && has_id && (!is_banned)

🧪 运算符重载

自定义运算符

ruby
class Vector
  attr_reader :x, :y
  
  def initialize(x, y)
    @x = x
    @y = y
  end
  
  # 重载加法运算符
  def +(other)
    Vector.new(@x + other.x, @y + other.y)
  end
  
  # 重载减法运算符
  def -(other)
    Vector.new(@x - other.x, @y - other.y)
  end
  
  # 重载乘法运算符
  def *(scalar)
    Vector.new(@x * scalar, @y * scalar)
  end
  
  # 重载相等运算符
  def ==(other)
    other.is_a?(Vector) && @x == other.x && @y == other.y
  end
  
  # 重载字符串转换运算符
  def to_s
    "(#{@x}, #{@y})"
  end
end

# 使用自定义运算符
v1 = Vector.new(1, 2)
v2 = Vector.new(3, 4)

v3 = v1 + v2
puts v3  # (4, 6)

v4 = v2 - v1
puts v4  # (2, 2)

v5 = v1 * 3
puts v5  # (3, 6)

puts v1 == Vector.new(1, 2)  # true

🎯 运算符最佳实践

1. 选择合适的运算符

ruby
# 好的做法:使用直观的运算符
if user.age >= 18
  puts "成年人"
end

# 避免复杂的运算符组合
# bad: result = a && b || c && d
# good: 
has_permission = a && b
has_exception = c && d
result = has_permission || has_exception

2. 合理使用短路求值

ruby
# 安全的条件检查
def process_user(user)
  # 利用短路求值避免nil错误
  if user && user.active? && user.profile && user.profile.complete?
    # 处理用户
  end
end

# 使用安全导航运算符(Ruby 2.3+)
def process_user_modern(user)
  if user&.active? && user&.profile&.complete?
    # 处理用户
  end
end

3. 运算符重载的谨慎使用

ruby
class Money
  attr_reader :amount, :currency
  
  def initialize(amount, currency = "CNY")
    @amount = amount
    @currency = currency
  end
  
  # 只重载有意义的运算符
  def +(other)
    if other.currency == @currency
      Money.new(@amount + other.amount, @currency)
    else
      # 货币转换逻辑
      raise "货币不匹配"
    end
  end
  
  # 提供清晰的比较方法
  def >(other)
    @amount > other.amount
  end
  
  def <(other)
    @amount < other.amount
  end
  
  def ==(other)
    other.is_a?(Money) && @amount == other.amount && @currency == other.currency
  end
  
  def to_s
    "#{@amount} #{@currency}"
  end
end

# 使用货币类
price1 = Money.new(100, "CNY")
price2 = Money.new(50, "CNY")
total = price1 + price2
puts total  # 150 CNY

🧪 实践示例

数学表达式计算器

ruby
class ExpressionCalculator
  def self.evaluate(expression)
    # 简单的表达式解析(仅作示例)
    # 实际应用中应使用更复杂的解析器
    
    # 移除空格
    expression = expression.gsub(/\s+/, "")
    
    # 处理乘除法
    while expression.match?(/[\*\/]/)
      expression.sub!(/(\d+(?:\.\d+)?)\*([+-]?\d+(?:\.\d+)?)/) do |match|
        $1.to_f * $2.to_f
      end
      
      expression.sub!(/(\d+(?:\.\d+)?)\/([+-]?\d+(?:\.\d+)?)/) do |match|
        $1.to_f / $2.to_f
      end
    end
    
    # 处理加减法
    while expression.match?(/[+-]/)
      expression.sub!(/([+-]?\d+(?:\.\d+)?)\+([+-]?\d+(?:\.\d+)?)/) do |match|
        $1.to_f + $2.to_f
      end
      
      expression.sub!(/([+-]?\d+(?:\.\d+)?)\-([+-]?\d+(?:\.\d+)?)/) do |match|
        $1.to_f - $2.to_f
      end
    end
    
    expression.to_f
  end
end

# 使用计算器
puts ExpressionCalculator.evaluate("2 + 3 * 4")     # 14.0
puts ExpressionCalculator.evaluate("10 / 2 - 3")    # 2.0
puts ExpressionCalculator.evaluate("2.5 * 4 + 1")   # 11.0

权限管理系统

ruby
class PermissionSystem
  # 使用位运算实现权限管理
  PERMISSIONS = {
    read: 1 << 0,      # 1
    write: 1 << 1,     # 2
    execute: 1 << 2,   # 4
    delete: 1 << 3,    # 8
    admin: 1 << 4      # 16
  }.freeze
  
  def initialize(initial_permissions = 0)
    @permissions = initial_permissions
  end
  
  def grant(*permissions)
    permissions.each do |perm|
      if PERMISSIONS.key?(perm)
        @permissions |= PERMISSIONS[perm]
      else
        raise ArgumentError, "未知权限: #{perm}"
      end
    end
    self
  end
  
  def revoke(*permissions)
    permissions.each do |perm|
      if PERMISSIONS.key?(perm)
        @permissions &= ~PERMISSIONS[perm]
      end
    end
    self
  end
  
  def has_permission?(permission)
    PERMISSIONS.key?(permission) && (@permissions & PERMISSIONS[permission]) != 0
  end
  
  def can_read?
    has_permission?(:read)
  end
  
  def can_write?
    has_permission?(:write)
  end
  
  def can_execute?
    has_permission?(:execute)
  end
  
  def is_admin?
    has_permission?(:admin)
  end
  
  def permissions_list
    PERMISSIONS.select { |name, value| (@permissions & value) != 0 }.keys
  end
  
  def to_s
    permissions_list.empty? ? "无权限" : permissions_list.join(", ")
  end
end

# 使用权限系统
user = PermissionSystem.new
puts user  # 无权限

user.grant(:read, :write)
puts user  # read, write
puts user.can_read?    # true
puts user.can_execute? # false

user.grant(:admin)
puts user  # read, write, admin
puts user.is_admin?    # true

user.revoke(:write)
puts user  # read, admin

📚 下一步学习

掌握了Ruby运算符后,建议继续学习:

继续您的Ruby学习之旅吧!

本站内容仅供学习和研究使用。