Ruby `<<` 操作符详解

<< 在 Ruby 里不是单纯的移位运算符(虽然数字也支持移位),更多是一个实例方法 #<<,不同类有完全不同的语义,是重载的操作符。

语法:obj << something

本质等价:obj.<<(something)

一、最常用场景:追加(可变对象原地修改)

1. String#<< 字符串追加(原地修改!重点)

<< 直接修改原字符串对象,不会生成新字符串,object_id 不变

ruby 复制代码
s = "hi"
puts s.object_id
s << " world"
puts s          # "hi world"
puts s.object_id # 和上面一样!原地修改

对比 +:s + "xxx" 返回新字符串,原对象不变。

ruby 复制代码
s = "hi"
s2 = s + " world"
p s # "hi"

2. Array#<< 数组追加元素(原地修改)

往数组尾部追加元素,等价于 push

ruby 复制代码
arr = [1,2]
arr << 3
p arr # [1,2,3]

# 链式调用,因为 << 返回自身
arr << 4 << 5
p arr # [1,2,3,4,5]

⚠️ 注意:<< 是追加一个元素

ruby 复制代码
arr = [1,2]
arr << [3,4]
p arr # [1,2,[3,4]] 嵌套数组!不是合并
# 如果想要合并数组,用 concat 或者 +
arr.concat([3,4])

3. Hash 不支持 <<

Hash 没有 #<< 方法,h << xxx 直接报错。

二、Integer#<< 位运算:左移(数字,不可变)

数字的 << 是二进制左移,数字是不可变对象,返回新数字,不修改原值

ruby 复制代码
1 << 2   # 1 的二进制 0b1 左移2位 → 0b100 = 4
# 公式:n << k = n * (2 ** k)
puts 3 << 2 # 3 * 4 =12

数字的 << 不会修改原变量:

ruby 复制代码
a = 3
a << 2
puts a # 3,不变!因为生成新数字,没有赋值回去
a = a << 2
puts a #12

三、其他内置类的 <<

  • IO#<<:向流写入内容(stdout << "hello")
ruby 复制代码
$stdout << "hello\n" # 等价 puts,但不自动换行
  • Range、Symbol:没有 << 方法

四、自定义类也可以重载 <<

Ruby 可以自己定义 << 方法:

ruby 复制代码
class Box
  def initialize
    @items = []
  end

  def <<(item)
    @items << item
    self # 返回自身,支持链式调用
  end

  attr_reader :items
end

b = Box.new
b << "apple" << "banana"
p b.items # ["apple", "banana"]

五、高频踩坑点

坑1:String#<< 原地修改,带来引用副作用

ruby 复制代码
s1 = "hello"
s2 = s1
s1 << "!"
puts s2 # hello!  s1 s2 指向同一个对象,一起变

这就是前面我们讲可变对象时的经典坑!

坑2:Array << 数组,会嵌套而不是扁平化

ruby 复制代码
arr = [1,2]
arr << [3,4]
p arr # [1,2,[3,4]] ❗嵌套

坑3:区分 << 和 +

对象 << +
String 原地修改原字符串,返回self 返回新字符串,原对象不变
Array 原地追加元素,返回self 返回新数组,合并内容
Integer 位左移,返回新整数 算术加法

六、快速记忆

  1. String / Array 的 <<:原地追加,返回自己,支持链式(可变对象,小心引用共享)
  2. Integer 的 <<:二进制左移,生成新数字
  3. obj << x 本质是调用 obj.<<(x),Ruby 运算符重载
相关推荐
灯澜忆梦1 天前
【RabbitMQ #13】 | 延迟消息
分布式·rabbitmq·ruby
灯澜忆梦2 天前
【RabbitMQ #11】 | 消费者可靠性
分布式·rabbitmq·ruby
zhangzeyuaaa2 天前
深入理解 Ruby 可变对象与不可变对象的原理、坑点与最佳实践
开发语言·后端·ruby
灯澜忆梦3 天前
【RabbitMQ #5】 | 三大交换机 Fanout ,Direct ,Topic
分布式·rabbitmq·ruby
灯澜忆梦4 天前
【RabbitMQ #7】 | 消息转换器
分布式·rabbitmq·ruby
Y38153266212 天前
Ruby 调用谷歌搜索 API:net/http 与 json 标准库实战
搜索引擎·ruby
程序员黎剑15 天前
RabbitMQ-消息可靠性-publisher-confirm持久化与手动ack
分布式·rabbitmq·ruby
我也要在julius_bar里藏钱15 天前
【山竹记账后端】1.搭建后端项目
后端·ruby·rails
星云API技术支持24 天前
企业微信二次开发:如何建立统一的错误处理、日志与请求追踪机制
javascript·企业微信·ruby