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 运算符重载
相关推荐
catino1 天前
RabbitMQ详解
分布式·rabbitmq·ruby
狂奔的sherry7 天前
JRuby 多线程反引号偶发 127:GC 提前释放了 posix_spawn 的 argv
java·linux·ruby·gc·jruby
zhangzeyuaaa14 天前
Ruby 多线程、GVL(GIL)与 Mutex 完全指南
开发语言·前端·ruby
zhangzeyuaaa14 天前
Ruby `require` 完全指南:从 `$LOAD_PATH` 到 `require_relative`
服务器·前端·ruby
zhangzeyuaaa14 天前
深入 Ruby:return 退出规则完全指南
开发语言·ruby
程序猿乐锅15 天前
从0-1一文详解RabbitMQ
java·分布式·后端·中间件·rabbitmq·ruby
zhangzeyuaaa17 天前
深入 Ruby:Block、Proc、Lambda 核心区别与最佳实践
开发语言·前端·ruby
zhangzeyuaaa18 天前
深入理解 Ruby 运算符:本质、分类、坑点与重载实战
开发语言·前端·ruby
zhangzeyuaaa18 天前
Ruby 方法参数完全指南:默认值、可变参数与关键字参数
前端·python·ruby
zhangzeyuaaa20 天前
Ruby Symbol 完全使用指南
ruby