Ruby Data Types
Ruby is a dynamically typed language where variables don't need explicit type declarations. This chapter will introduce in detail the various data types in Ruby and how to use them.
🎯 Ruby Type System Features
Dynamic Typing
ruby
# Variables can store any type of value
variable = 42 # Integer
variable = "Hello" # String
variable = [1, 2, 3] # Array
variable = {:name => "Zhang San"} # HashStrong Typing
ruby
# Ruby is a strongly typed language and does not allow implicit type conversion
number = 10
text = "20"
# result = number + text # This will raise TypeError
result = number + text.to_i # Explicit conversion requiredEverything is an Object
ruby
# In Ruby, all values are objects
puts 42.class # Integer
puts "Hello".class # String
puts true.class # TrueClass
puts nil.class # NilClass🔢 Numeric Types
Integers (Integer)
ruby
# Integer types
positive = 42
negative = -17
zero = 0
large_number = 123456789012345678901234567890
# Integer base representation
decimal = 42 # Decimal
binary = 0b101010 # Binary (42)
octal = 0o52 # Octal (42)
hexadecimal = 0x2A # Hexadecimal (42)
# Integer methods
puts 42.even? # true (is even)
puts 42.odd? # false (is odd)
puts 42.times { |i| print "#{i} " } # 0 1 2 ... 41
puts 42.next # 43 (next integer)
puts 42.pred # 41 (previous integer)Floats (Float)
ruby
# Float types
pi = 3.14159
negative_float = -2.5
scientific = 1.23e4 # 12300.0 (scientific notation)
# Float precision issues
puts 0.1 + 0.2 # 0.30000000000000004
puts (0.1 + 0.2).round(1) # 0.3
# Float methods
puts 3.14.floor # 3 (floor)
puts 3.14.ceil # 4 (ceiling)
puts 3.14.round # 3 (round)
puts 3.14.round(2) # 3.14 (keep 2 decimal places)
puts 3.14.abs # 3.14 (absolute value)Rational Numbers (Rational)
ruby
# Rational number type (exact fraction representation)
require 'rational'
fraction = Rational(2, 3) # 2/3
puts fraction # (2/3)
puts fraction.to_f # 0.6666666666666666
# Rational number operations (no precision loss)
result = Rational(1, 2) + Rational(1, 3)
puts result # (5/6)
# Other ways to create rationals
fraction1 = 2/3r # Using r suffix
fraction2 = Rational("2/3") # Create from stringComplex Numbers (Complex)
ruby
# Complex number type
require 'complex'
complex_number = Complex(3, 4) # 3+4i
puts complex_number # (3+4i)
puts complex_number.real # 3 (real part)
puts complex_number.imag # 4 (imaginary part)
puts complex_number.abs # 5.0 (modulus)
# Complex number operations
a = Complex(1, 2)
b = Complex(3, 4)
puts a + b # (4+6i)
puts a * b # (-5+10i)📝 Text Types
Strings (String)
ruby
# String creation
single_quoted = 'Single-quoted string'
double_quoted = "Double-quoted string"
heredoc = <<~TEXT
Multi-line string
Can contain multiple lines
Supports indentation
TEXT
# String interpolation (double-quotes only)
name = "Zhang San"
age = 25
greeting = "Hello, #{name}! You are #{age} years old."
puts greeting
# String methods
text = "Hello, World!"
puts text.length # 13 (length)
puts text.upcase # HELLO, WORLD! (uppercase)
puts text.downcase # hello, world! (lowercase)
puts text.capitalize # Hello, world! (capitalize first letter)
puts text.reverse # !dlroW ,olleH (reverse)
puts text.include?("World") # true (contains substring)
# String operations
original = "Ruby Programming"
puts original[0] # R (index access)
puts original[0..3] # Ruby (slice)
puts original[4..-1] # Programming (from 5th character to end)
# String modification
mutable_string = "Hello"
mutable_string << " World" # Append
puts mutable_string # Hello World
# String encoding
chinese_text = "Chinese Text"
puts chinese_text.encoding # UTF-8🧠 Boolean Types
TrueClass and FalseClass
ruby
# Boolean values
is_true = true
is_false = false
# Boolean methods
puts true.class # TrueClass
puts false.class # FalseClass
# Boolean operations
puts true && false # false (and)
puts true || false # true (or)
puts !true # false (not)
# Truthy and falsy values
# In Ruby, only false and nil are falsy, everything else is truthy
puts !!true # true
puts !!false # false
puts !!nil # false
puts !!0 # true (0 is truthy!)
puts !!"" # true (empty string is truthy!)
puts !!"Hello" # true📦 Collection Types
Arrays (Array)
ruby
# Array creation
empty_array = []
numbers = [1, 2, 3, 4, 5]
mixed_array = ["String", 42, true, nil]
nested_array = [[1, 2], [3, 4], [5, 6]]
# Array access
fruits = ["Apple", "Banana", "Orange"]
puts fruits[0] # Apple
puts fruits[-1] # Orange (last element)
puts fruits[1..2] # ["Banana", "Orange"] (slice)
# Array methods
puts fruits.length # 3 (length)
puts fruits.size # 3 (size)
puts fruits.empty? # false (is empty)
puts fruits.include?("Apple") # true (contains)
# Array operations
fruits.push("Grape") # Add to end
fruits << "Strawberry" # Add to end (shorthand)
first_fruit = fruits.shift # Remove and return first element
last_fruit = fruits.pop # Remove and return last element
fruits.unshift("Watermelon") # Add to beginning
# Array iteration
numbers = [1, 2, 3, 4, 5]
numbers.each { |n| puts n } # Traverse
doubled = numbers.map { |n| n * 2 } # Transform
evens = numbers.select { |n| n.even? } # Filter
sum = numbers.reduce(0) { |acc, n| acc + n } # ReduceHashes (Hash)
ruby
# Hash creation
empty_hash = {}
person = {
"name" => "Zhang San",
"age" => 25,
"city" => "Beijing"
}
# Using symbols as keys (recommended)
person_symbol = {
name: "Zhang San",
age: 25,
city: "Beijing"
}
# Hash access
puts person["name"] # Zhang San
puts person_symbol[:name] # Zhang San
# Hash methods
puts person.keys # ["name", "age", "city"]
puts person.values # ["Zhang San", 25, "Beijing"]
puts person.length # 3
puts person.empty? # false
# Hash operations
person["job"] = "Programmer" # Add key-value pair
person[:age] = 26 # Modify value
person.delete("city") # Delete key-value pair
# Hash iteration
person_symbol.each do |key, value|
puts "#{key}: #{value}"
end
# Hash default values
scores = Hash.new(0) # Default value is 0
scores[:math] = 95
puts scores[:english] # 0 (default value)Ranges (Range)
ruby
# Range creation
inclusive_range = 1..10 # Includes 10
exclusive_range = 1...10 # Does not include 10
# Character ranges
letters = 'a'..'z'
# Range methods
puts (1..5).include?(3) # true
puts (1..5).min # 1
puts (1..5).max # 5
puts (1..5).size # 5
# Range conversion
array_from_range = (1..5).to_a # [1, 2, 3, 4, 5]
string_from_range = ('a'..'e').to_a.join # "abcde"
# Range iteration
(1..5).each { |n| puts n } # 1 2 3 4 5🎭 Special Types
Symbols (Symbol)
ruby
# Symbol creation
symbol1 = :name
symbol2 = :"user-name"
symbol3 = :"user name"
# Difference between symbols and strings
string_key = "name"
symbol_key = :name
puts string_key.object_id # Different every time
puts symbol_key.object_id # Always the same
# Symbol methods
puts :hello.to_s # hello
puts "hello".to_sym # :hello
puts :Name.capitalize # :Name
# Symbols in hashes
user = {
name: "Zhang San",
age: 25,
email: "zhangsan@example.com"
}Nil (NilClass)
ruby
# Nil values
value = nil
puts value.class # NilClass
# Nil checks
puts value.nil? # true
puts value == nil # true
# Safe navigation operator
user = nil
puts user&.name # nil (won't raise error)
puts user&.name&.upcase # nil
# Nil's boolean value
puts !!nil # falseRegular Expressions (Regexp)
ruby
# Regular expression creation
pattern1 = /ruby/i # Case insensitive
pattern2 = %r{https?://} # Using %r delimiter
# Regular expression matching
text = "I love Ruby programming"
puts text =~ /ruby/i # 7 (match position)
puts text.match?(/ruby/i) # true (matches?)
# Regular expression capture
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🔄 Type Conversion
Explicit Type Conversion
ruby
# String conversion
puts 42.to_s # "42"
puts true.to_s # "true"
puts [1, 2, 3].to_s # "[1, 2, 3]"
# Numeric conversion
puts "42".to_i # 42
puts "3.14".to_f # 3.14
puts "hello".to_i # 0 (returns 0 for invalid)
# Array and hash conversion
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}Type Checking
ruby
# Type checking methods
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
# Respond to method check
puts "hello".respond_to?(:upcase) # true
puts 42.respond_to?(:times) # true
# Instance check
puts 42.instance_of?(Integer) # true
puts 42.instance_of?(Numeric) # false🧪 Type System Practice
Advantages of Dynamic Typing
ruby
# Flexible parameter handling
def process_data(data)
case data
when String
puts "Processing string: #{data.upcase}"
when Numeric
puts "Processing number: #{data * 2}"
when Array
puts "Processing array: #{data.join(', ')}"
when Hash
puts "Processing hash: #{data.keys.join(', ')}"
else
puts "Unknown type: #{data.class}"
end
end
# Test with different types of data
process_data("hello") # Processing string: HELLO
process_data(42) # Processing number: 84
process_data([1, 2, 3]) # Processing array: 1, 2, 3
process_data({a: 1, b: 2}) # Processing hash: a, bType Safety Practices
ruby
# Type-safe method design
class Calculator
def add(a, b)
# Validate parameter types
raise ArgumentError, "Parameters must be numbers" unless a.is_a?(Numeric) && b.is_a?(Numeric)
a + b
end
def multiply_array(numbers)
# Validate parameter type
raise ArgumentError, "Parameter must be an array" unless numbers.is_a?(Array)
# Validate array element types
unless numbers.all? { |n| n.is_a?(Numeric) }
raise ArgumentError, "Array elements must all be numbers"
end
numbers.reduce(1) { |product, n| product * n }
end
end
# Usage example
calc = Calculator.new
puts calc.add(2, 3) # 5
# puts calc.add("2", 3) # Will raise ArgumentErrorCustom Data Types
ruby
# Create custom class
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
# Use custom type
point = Point.new(3, 4)
puts point # (3, 4)
puts point.distance_from_origin # 5.0🎯 Data Type Best Practices
1. Choose Appropriate Data Types
ruby
# Use symbols as hash keys
# Good practice
user = {
name: "Zhang San",
age: 25,
active: true
}
# Avoid using strings as keys
# Not recommended
user = {
"name" => "Zhang San",
"age" => 25,
"active" => true
}2. Safe Type Conversion
ruby
# Safe type conversion
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. Handling Nil Values
ruby
# Safely handle nil values
def safe_string_operation(str)
return "" if str.nil?
str.to_s.strip
end
# Use ternary operator
def get_display_name(user)
user&.name || "Anonymous User"
end
# Use default values
def process_options(options = {})
debug = options[:debug] || false
timeout = options[:timeout] || 30
# Process options
end📚 Next Steps
After mastering Ruby data types, it is recommended to continue learning:
- Ruby Variables - Learn variable scope and usage
- Ruby Strings - Deep dive into string operations
- Ruby Arrays - Master advanced array usage
- Ruby Hashes - Learn more hash features
Continue your Ruby learning journey!