Ruby 数据类型
前一章学了"变量是装值的容器",这一章讲"容器里装什么"。Ruby 内置的数据类型不算多,但每个都有极其丰富的方法。本章先给个总览,后面会专门用整章讲字符串、数组、哈希三个最重要的。
1. 数值(Numeric)
Ruby 的数值分两大类:Integer(整数) 和 Float(浮点数)。Ruby 2.4 之后不再分 Fixnum 和 Bignum,统一用 Integer:
# 整数(Integer):不分 int/long,自动用大数
age = 25
year = 2026
big = 10 ** 20 # 大整数也自动支持
puts age.class # Integer
puts big.class # Integer
# 浮点数(Float)
pi = 3.14159
puts pi.class # Float
# 整数除法 vs 浮点除法
puts 7 / 2 # 3(整数除整数,结果是整数,向下取整)
puts 7.0 / 2 # 3.5(其中一个为浮点,结果为浮点)
puts 7.fdiv(2) # 3.5(强制浮点除法)新手最易踩的坑是整数除法:7 / 2 得到 3(向下取整),不是 3.5。要浮点结果,把任一操作数写成浮点(7.0),或用 fdiv 方法。
2. 布尔值与 nil
Ruby 的真假对象是 true(TrueClass 的唯一实例)和 false(FalseClass 的唯一实例)。还有一个表示"无"的特殊对象 nil(NilClass 的唯一实例):
# true / false 是对象
puts true.class # TrueClass
puts false.class # FalseClass
# nil 表示"什么都没有",类似其他语言的 null
x = nil
puts x.class # NilClass
puts x.nil? # true
puts x.to_s # ""(空字符串,Rails 还会把它显示成 "")
puts x || "默认值" # 默认值(|| 短路求值是惯用法)前面语法章提过:只有 nil 和 false 是假。所以 x || "默认值" 是 Ruby 里设置默认值的惯用法——当 x 是 nil 或 false 时用后面的值。
3. 字符串(String)
字符串是 Ruby 用得最多的类型。它分单引号和双引号两种:
# 双引号:支持插值和转义
name = "小明"
puts "你好, #{name}" # 你好, 小明
puts "行1\n行2" # 换行(在反引号模板里要写 \n)
# 单引号:几乎不解析任何东西
puts '你好, #{name}' # 你好, #{name}(原样输出)
puts '行1\n行2' # 行1
行2(单引号里 \n 仍是字面)
# 字符串拼接
puts "a" + "b" # ab
puts "a" * 3 # aaa(乘法重复)差异在于:
- 双引号支持插值(把变量嵌入字符串)和转义(换行等)。
- 单引号几乎不解析,你写什么就是什么(转义只认
\\'和\\\\)。
实际项目里 95% 用双引号。单引号用在"字符串里有引号、且不需要插值"的场景,性能略快一点点(可忽略)。
4. 符号(Symbol)
符号是 Ruby 独有的一种类型,以冒号开头。它是不可变的、全局唯一的"标签":
# 符号(Symbol):轻量、不可变的"标签"
status = :active
puts status.class # Symbol
puts status # active
puts status.to_s # "active"(转字符串)
# 符号 vs 字符串
puts :name.object_id # 一个固定数字
puts :name.object_id # 同样的数字(全局唯一)
puts "name".object_id # 每次不同
puts "name".object_id # 又一个不同数字
# 当键用,符号更快更省内存
config = { name: "小明", age: 18 } # 等价于 { :name => "小明", :age => 18 }核心区别:字符串每次创建都是新对象("name".object_id 每次不同),符号全局唯一(:name.object_id 永远相同)。所以当字典的键、当方法名、当状态标签用符号更省内存。Rails 里到处是 params[:id] 这种符号键。
新手口诀:内容用字符串,名字用符号。
5. 数组(Array)
数组是有序集合,可以放任何类型的元素:
# 数组:有序集合,元素类型可以混合
nums = [1, 2, 3, 4, 5]
mixed = [1, "two", 3.0, :four]
empty = []
puts nums.class # Array
puts nums.first # 1
puts nums.last # 5
puts nums[-1] # 5(负索引从末尾数)
puts nums.length # 5
# %w 快速生成字符串数组(单词数组)
words = %w[apple banana cherry]
puts words.inspect # ["apple", "banana", "cherry"]数组有非常非常丰富的方法——map、select、reduce、sort、each 等等。后面有专门一章讲。
6. 哈希(Hash)
哈希是键值对集合,类似 JS 的对象、Python 的 dict:
# 哈希:键值对
person = {
name: "小明",
age: 18,
city: "北京"
}
puts person.class # Hash
puts person[:name] # 小明
puts person[:age] # 18
# 老语法(Hash Rocket)
old = { :name => "小明", :age => 18 }
# 跟新语法等价,新手优先用新语法(name: 是 :name => 的简写)新手最易混淆的是两种语法——新语法 name: value 实际上是 :name => value 的简写,只对全符号键有效。如果键不是符号(比如字符串键或数字键),只能用 Hash Rocket =>。
7. 范围(Range)
范围表示一个区间,有两个点 ..(包含末尾)和三个点 ...(不含末尾):
# 范围(Range):表示一个区间
r1 = 1..5 # 包含末尾(1,2,3,4,5)
r2 = 1...5 # 不含末尾(1,2,3,4)
puts r1.to_a.inspect # [1, 2, 3, 4, 5]
puts r2.to_a.inspect # [1, 2, 3, 4]
# 常用于遍历和判断
(1..3).each { |i| puts i }
puts (1..10).include?(5) # true
puts ('a'..'e').to_a.inspect范围常用在 for 循环、case 分支、批量生成数据。Rails 的分页常用 Post.all[10..19] 取第 10 到 19 条。
8. 类型查询与转换
因为 Ruby 是动态类型,经常需要判断类型或转换类型:
# 用 .class 查类型
puts 5.class # Integer
puts "hi".class # String
puts [].class # Array
puts({}.class) # Hash
puts :foo.class # Symbol
# 用 is_a? 判断是否属于某类型(包括父类)
puts 5.is_a?(Integer) # true
puts 5.is_a?(Numeric) # true(Numeric 是 Integer 的父)
puts "hi".is_a?(String) # true
# 类型转换
puts "42".to_i # 42
puts 42.to_s # "42"
puts "3.14".to_f # 3.14
puts 0.to_s # "0"常用转换方法:to_i(转整数)、to_f(转浮点)、to_s(转字符串)、to_a(转数组)、to_h(转哈希)、to_sym(字符串转符号)。
9. 类型总览
- 数值:Integer、Float(还有 Rational、Complex,少用)。
- 字符串:String(可变,这点和 Python/JS 不同)。
- 符号:Symbol(不可变,轻量)。
- 集合:Array、Hash、Range、Set(需 require)。
- 布尔/空:TrueClass、FalseClass、NilClass。
- 其他:正则 Regexp、时间 Time、文件 File 等等。
小结
本章你浏览了 Ruby 的内置类型。数值、布尔、符号、范围相对简单;字符串、数组、哈希因为方法太多,后续各有一章专门讲。下一篇先看运算符——学会怎么操作这些数据。
← 上一篇 Ruby 变量
下一篇 Ruby 运算符 →