Skip to content

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)    # 3

3. 空值处理

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学习之旅吧!

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