Ruby 数据类型
Ruby是一种动态类型语言,变量不需要显式声明类型。本章将详细介绍Ruby中的各种数据类型及其使用方法。
🎯 Ruby类型系统特点
动态类型
ruby
# 变量可以存储任何类型的值
variable = 42 # 整数
variable = "Hello" # 字符串
variable = [1, 2, 3] # 数组
variable = {:name => "张三"} # 哈希强类型
ruby
# Ruby是强类型语言,不允许隐式类型转换
number = 10
text = "20"
# result = number + text # 这会引发TypeError
result = number + text.to_i # 需要显式转换一切都是对象
ruby
# 在Ruby中,所有值都是对象
puts 42.class # Integer
puts "Hello".class # String
puts true.class # TrueClass
puts nil.class # NilClass🔢 数值类型
整数 (Integer)
ruby
# 整数类型
positive = 42
negative = -17
zero = 0
large_number = 123456789012345678901234567890
# 整数进制表示
decimal = 42 # 十进制
binary = 0b101010 # 二进制 (42)
octal = 0o52 # 八进制 (42)
hexadecimal = 0x2A # 十六进制 (42)
# 整数方法
puts 42.even? # true (是否偶数)
puts 42.odd? # false (是否奇数)
puts 42.times { |i| print "#{i} " } # 0 1 2 ... 41
puts 42.next # 43 (下一个整数)
puts 42.pred # 41 (前一个整数)浮点数 (Float)
ruby
# 浮点数类型
pi = 3.14159
negative_float = -2.5
scientific = 1.23e4 # 12300.0 (科学计数法)
# 浮点数精度问题
puts 0.1 + 0.2 # 0.30000000000000004
puts (0.1 + 0.2).round(1) # 0.3
# 浮点数方法
puts 3.14.floor # 3 (向下取整)
puts 3.14.ceil # 4 (向上取整)
puts 3.14.round # 3 (四舍五入)
puts 3.14.round(2) # 3.14 (保留2位小数)
puts 3.14.abs # 3.14 (绝对值)有理数 (Rational)
ruby
# 有理数类型(精确的分数表示)
require 'rational'
fraction = Rational(2, 3) # 2/3
puts fraction # (2/3)
puts fraction.to_f # 0.6666666666666666
# 有理数运算(无精度损失)
result = Rational(1, 2) + Rational(1, 3)
puts result # (5/6)
# 创建有理数的其他方式
fraction1 = 2/3r # 使用r后缀
fraction2 = Rational("2/3") # 从字符串创建复数 (Complex)
ruby
# 复数类型
require 'complex'
complex_number = Complex(3, 4) # 3+4i
puts complex_number # (3+4i)
puts complex_number.real # 3 (实部)
puts complex_number.imag # 4 (虚部)
puts complex_number.abs # 5.0 (模)
# 复数运算
a = Complex(1, 2)
b = Complex(3, 4)
puts a + b # (4+6i)
puts a * b # (-5+10i)📝 文本类型
字符串 (String)
ruby
# 字符串创建
single_quoted = '单引号字符串'
double_quoted = "双引号字符串"
heredoc = <<~TEXT
多行字符串
可以包含多行内容
支持缩进
TEXT
# 字符串插值(仅双引号)
name = "张三"
age = 25
greeting = "你好, #{name}! 你今年#{age}岁了。"
puts greeting
# 字符串方法
text = "Hello, World!"
puts text.length # 13 (长度)
puts text.upcase # HELLO, WORLD! (大写)
puts text.downcase # hello, world! (小写)
puts text.capitalize # Hello, world! (首字母大写)
puts text.reverse # !dlroW ,olleH (反转)
puts text.include?("World") # true (包含子串)
# 字符串操作
original = "Ruby编程"
puts original[0] # R (索引访问)
puts original[0..3] # Ruby (切片)
puts original[4..-1] # 编程 (从第5个字符到末尾)
# 字符串修改
mutable_string = "Hello"
mutable_string << " World" # 追加
puts mutable_string # Hello World
# 字符串编码
chinese_text = "中文"
puts chinese_text.encoding # UTF-8🧠 布尔类型
TrueClass 和 FalseClass
ruby
# 布尔值
is_true = true
is_false = false
# 布尔方法
puts true.class # TrueClass
puts false.class # FalseClass
# 布尔运算
puts true && false # false (与)
puts true || false # true (或)
puts !true # false (非)
# 真值和假值
# 在Ruby中,只有false和nil为假值,其他都是真值
puts !!true # true
puts !!false # false
puts !!nil # false
puts !!0 # true (0是真值!)
puts !!"" # true (空字符串是真值!)
puts !!"Hello" # true📦 集合类型
数组 (Array)
ruby
# 数组创建
empty_array = []
numbers = [1, 2, 3, 4, 5]
mixed_array = ["字符串", 42, true, nil]
nested_array = [[1, 2], [3, 4], [5, 6]]
# 数组访问
fruits = ["苹果", "香蕉", "橙子"]
puts fruits[0] # 苹果
puts fruits[-1] # 橙子 (最后一个元素)
puts fruits[1..2] # ["香蕉", "橙子"] (切片)
# 数组方法
puts fruits.length # 3 (长度)
puts fruits.size # 3 (大小)
puts fruits.empty? # false (是否为空)
puts fruits.include?("苹果") # true (是否包含)
# 数组操作
fruits.push("葡萄") # 添加到末尾
fruits << "草莓" # 添加到末尾 (简写)
first_fruit = fruits.shift # 移除并返回第一个元素
last_fruit = fruits.pop # 移除并返回最后一个元素
fruits.unshift("西瓜") # 添加到开头
# 数组迭代
numbers = [1, 2, 3, 4, 5]
numbers.each { |n| puts n } # 遍历
doubled = numbers.map { |n| n * 2 } # 转换
evens = numbers.select { |n| n.even? } # 筛选
sum = numbers.reduce(0) { |acc, n| acc + n } # 归约哈希 (Hash)
ruby
# 哈希创建
empty_hash = {}
person = {
"name" => "张三",
"age" => 25,
"city" => "北京"
}
# 符号作为键(推荐)
person_symbol = {
name: "张三",
age: 25,
city: "北京"
}
# 哈希访问
puts person["name"] # 张三
puts person_symbol[:name] # 张三
# 哈希方法
puts person.keys # ["name", "age", "city"]
puts person.values # ["张三", 25, "北京"]
puts person.length # 3
puts person.empty? # false
# 哈希操作
person["job"] = "程序员" # 添加键值对
person[:age] = 26 # 修改值
person.delete("city") # 删除键值对
# 哈希迭代
person_symbol.each do |key, value|
puts "#{key}: #{value}"
end
# 哈希默认值
scores = Hash.new(0) # 默认值为0
scores[:math] = 95
puts scores[:english] # 0 (默认值)范围 (Range)
ruby
# 范围创建
inclusive_range = 1..10 # 包含10
exclusive_range = 1...10 # 不包含10
# 字符范围
letters = 'a'..'z'
# 范围方法
puts (1..5).include?(3) # true
puts (1..5).min # 1
puts (1..5).max # 5
puts (1..5).size # 5
# 范围转换
array_from_range = (1..5).to_a # [1, 2, 3, 4, 5]
string_from_range = ('a'..'e').to_a.join # "abcde"
# 范围迭代
(1..5).each { |n| puts n } # 1 2 3 4 5🎭 特殊类型
符号 (Symbol)
ruby
# 符号创建
symbol1 = :name
symbol2 = :"user-name"
symbol3 = :"user name"
# 符号与字符串的区别
string_key = "name"
symbol_key = :name
puts string_key.object_id # 每次都不同
puts symbol_key.object_id # 总是相同
# 符号方法
puts :hello.to_s # hello
puts "hello".to_sym # :hello
puts :Name.capitalize # :Name
# 符号在哈希中的应用
user = {
name: "张三",
age: 25,
email: "zhangsan@example.com"
}Nil (NilClass)
ruby
# Nil值
value = nil
puts value.class # NilClass
# Nil检查
puts value.nil? # true
puts value == nil # true
# 安全导航操作符
user = nil
puts user&.name # nil (不会引发错误)
puts user&.name&.upcase # nil
# Nil的布尔值
puts !!nil # false正则表达式 (Regexp)
ruby
# 正则表达式创建
pattern1 = /ruby/i # 忽略大小写
pattern2 = %r{https?://} # 使用%r分隔符
# 正则表达式匹配
text = "I love Ruby programming"
puts text =~ /ruby/i # 7 (匹配位置)
puts text.match?(/ruby/i) # true (是否匹配)
# 正则表达式捕获
match_data = "2023-12-25".match(/(\d{4})-(\d{2})-(\d{2})/)
puts match_data[0] # 2023-12-25
puts match_data[1] # 2023
puts match_data[2] # 12
puts match_data[3] # 25🔄 类型转换
显式类型转换
ruby
# 字符串转换
puts 42.to_s # "42"
puts true.to_s # "true"
puts [1, 2, 3].to_s # "[1, 2, 3]"
# 数值转换
puts "42".to_i # 42
puts "3.14".to_f # 3.14
puts "hello".to_i # 0 (无效时返回0)
# 数组和哈希转换
puts "hello".chars # ["h", "e", "l", "l", "o"]
puts [1, 2, 3].join("-") # "1-2-3"
puts [["a", 1], ["b", 2]].to_h # {"a"=>1, "b"=>2}类型检查
ruby
# 类型检查方法
puts 42.is_a?(Integer) # true
puts "hello".is_a?(String) # true
puts [1, 2, 3].is_a?(Array) # true
puts {:a => 1}.is_a?(Hash) # true
# 响应方法检查
puts "hello".respond_to?(:upcase) # true
puts 42.respond_to?(:times) # true
# 实例检查
puts 42.instance_of?(Integer) # true
puts 42.instance_of?(Numeric) # false🧪 类型系统实践
动态类型的优势
ruby
# 灵活的参数处理
def process_data(data)
case data
when String
puts "处理字符串: #{data.upcase}"
when Numeric
puts "处理数字: #{data * 2}"
when Array
puts "处理数组: #{data.join(', ')}"
when Hash
puts "处理哈希: #{data.keys.join(', ')}"
else
puts "未知类型: #{data.class}"
end
end
# 测试不同类型的数据
process_data("hello") # 处理字符串: HELLO
process_data(42) # 处理数字: 84
process_data([1, 2, 3]) # 处理数组: 1, 2, 3
process_data({a: 1, b: 2}) # 处理哈希: a, b类型安全实践
ruby
# 类型安全的方法设计
class Calculator
def add(a, b)
# 验证参数类型
raise ArgumentError, "参数必须是数字" unless a.is_a?(Numeric) && b.is_a?(Numeric)
a + b
end
def multiply_array(numbers)
# 验证参数类型
raise ArgumentError, "参数必须是数组" unless numbers.is_a?(Array)
# 验证数组元素类型
unless numbers.all? { |n| n.is_a?(Numeric) }
raise ArgumentError, "数组元素必须都是数字"
end
numbers.reduce(1) { |product, n| product * n }
end
end
# 使用示例
calc = Calculator.new
puts calc.add(2, 3) # 5
# puts calc.add("2", 3) # 会引发ArgumentError自定义数据类型
ruby
# 创建自定义类
class Point
attr_accessor :x, :y
def initialize(x, y)
@x = x
@y = y
end
def distance_from_origin
Math.sqrt(@x**2 + @y**2)
end
def to_s
"(#{@x}, #{@y})"
end
end
# 使用自定义类型
point = Point.new(3, 4)
puts point # (3, 4)
puts point.distance_from_origin # 5.0🎯 数据类型最佳实践
1. 选择合适的数据类型
ruby
# 使用符号作为哈希键
# 好的做法
user = {
name: "张三",
age: 25,
active: true
}
# 避免使用字符串作为键
# 不推荐
user = {
"name" => "张三",
"age" => 25,
"active" => true
}2. 类型转换安全
ruby
# 安全的类型转换
def safe_to_integer(value)
case value
when Integer
value
when String
Integer(value) rescue 0
when Float
value.to_i
else
0
end
end
puts safe_to_integer("42") # 42
puts safe_to_integer("abc") # 0
puts safe_to_integer(3.14) # 33. 空值处理
ruby
# 安全处理nil值
def safe_string_operation(str)
return "" if str.nil?
str.to_s.strip
end
# 使用三元运算符
def get_display_name(user)
user&.name || "匿名用户"
end
# 使用默认值
def process_options(options = {})
debug = options[:debug] || false
timeout = options[:timeout] || 30
# 处理选项
end📚 下一步学习
掌握了Ruby数据类型后,建议继续学习:
- Ruby 变量 - 学习变量的作用域和使用
- Ruby 字符串(String) - 深入学习字符串操作
- Ruby 数组(Array) - 掌握数组的高级用法
- Ruby 哈希(Hash) - 学习哈希的更多特性
继续您的Ruby学习之旅吧!