Ruby空值 #

一、nil概述 #

nil 是Ruby中表示"无值"或"空"的特殊对象,它是 NilClass 类的唯一实例。

ruby
nil.class
nil.nil?
nil.object_id
nil.to_s
nil.inspect

二、nil的特点 #

2.1 唯一实例 #

ruby
nil.equal?(nil)
nil.object_id
nil.class
NilClass.instance_methods

2.2 布尔值 #

在条件判断中,nil 被视为假值:

ruby
if nil
  puts "不会执行"
else
  puts "nil是假值"
end

!!nil
!nil

2.3 与false的区别 #

ruby
nil == false
nil.eql?(false)
nil.equal?(false)
nil.class
false.class
nil.nil?
false.nil?

三、nil的来源 #

3.1 未初始化的变量 #

ruby
puts undefined_var

@instance_var
@@class_var
$global_var

3.2 数组/哈希越界访问 #

ruby
arr = [1, 2, 3]
arr[10]

hash = { a: 1 }
hash[:b]
hash[:nonexistent]

3.3 方法默认返回值 #

ruby
def do_nothing
end

result = do_nothing
puts result

def early_return
  return
  puts "不会执行"
end

result = early_return
puts result

3.4 正则匹配失败 #

ruby
"hello" =~ /world/
"hello".match(/world/)

3.5 查找方法未找到 #

ruby
arr = [1, 2, 3]
arr.find { |n| n > 10 }

arr.index(10)
arr.rindex(10)

四、nil检查方法 #

4.1 nil?方法 #

ruby
value = nil
value.nil?

value = "hello"
value.nil?

value = false
value.nil?

4.2 条件判断 #

ruby
value = nil

if value
  puts "有值"
else
  puts "无值或false"
end

if !value.nil?
  puts "不是nil"
end

unless value.nil?
  puts "不是nil"
end

4.3 安全导航操作符 #

Ruby 2.3+ 提供了安全导航操作符 &.

ruby
user = nil

user&.name
user&.profile&.avatar

user&.name&.upcase

user&.name || "Guest"

4.4 dig方法 #

ruby
data = { user: { profile: { name: "Ruby" } } }

data.dig(:user, :profile, :name)
data.dig(:user, :settings, :theme)

data = nil
data&.dig(:user)

五、nil的转换方法 #

5.1 基本转换 #

ruby
nil.to_s
nil.to_i
nil.to_f
nil.to_a
nil.to_h
nil.to_r
nil.to_c

5.2 数组转换 #

ruby
nil.to_a
Array(nil)
[*nil]

5.3 哈希转换 #

ruby
nil.to_h
Hash(nil)

5.4 自定义nil转换 #

ruby
class NilClass
  def to_boolean
    false
  end
end

nil.to_boolean

六、处理nil的模式 #

6.1 默认值 #

ruby
name = nil
name = name || "Guest"
name ||= "Guest"

name = params[:name] || "Guest"
name = params[:name] || params[:nickname] || "Guest"

6.2 fetch方法 #

ruby
hash = { a: 1 }

hash.fetch(:a)
hash.fetch(:b)
hash.fetch(:b, "default")
hash.fetch(:b) { |key| "#{key} not found" }

6.3 values_at #

ruby
hash = { a: 1, b: 2 }
hash.values_at(:a, :b, :c)

6.4 compact #

ruby
arr = [1, nil, 2, nil, 3]
arr.compact
arr.compact!

hash = { a: 1, b: nil, c: 3 }
hash.compact
hash.compact!

6.5 presence(ActiveSupport) #

ruby
require 'active_support/core_ext/object/blank'

nil.presence
"".presence
"hello".presence

name = nil
name.presence || "Guest"

params = { nickname: "Ruby" }
username = params[:name].presence || params[:nickname].presence || "Guest"

七、nil与异常 #

7.1 NoMethodError #

ruby
nil.name

nil + 1
nil.length

7.2 安全处理 #

ruby
def safe_method(obj)
  return unless obj

  obj.process
end

def safe_access(hash, key)
  hash&.[](key)
end

7.3 try方法(ActiveSupport) #

ruby
require 'active_support/core_ext/object/try'

nil.try(:name)
nil.try(:profile).try(:avatar)

nil&.name

八、nil在集合中的处理 #

8.1 数组中的nil #

ruby
arr = [1, nil, 2, nil, 3]

arr.compact
arr.reject(&:nil?)
arr.select { |n| !n.nil? }
arr.count(&:nil?)
arr.any?(&:nil?)

8.2 哈希中的nil #

ruby
hash = { a: 1, b: nil, c: 3 }

hash.compact
hash.reject { |_, v| v.nil? }
hash.select { |_, v| !v.nil? }

8.3 迭代中的nil #

ruby
arr = [1, nil, 2, nil, 3]

arr.map { |n| n&.to_s }
arr.filter_map { |n| n&.to_s }
arr.map { |n| n&.to_s }.compact

九、nil的特殊用法 #

9.1 作为哨兵值 #

ruby
def find_item(id, default = nil)
  items.find { |item| item.id == id } || default
end

result = find_item(1)
result = find_item(999, "Not Found")

9.2 条件返回 #

ruby
def find_user(id)
  user = database.find(id)
  return nil unless user.active?

  user
end

def process(data)
  return if data.nil?

  data.transform
end

9.3 空对象模式 #

ruby
class User
  def name
    @name
  end

  def admin?
    false
  end
end

class NullUser
  def name
    "Guest"
  end

  def admin?
    false
  end

  def nil?
    true
  end
end

def current_user
  @current_user || NullUser.new
end

puts current_user.name
puts current_user.admin?

十、nil的常见陷阱 #

10.1 nil检查混淆 #

ruby
value = false

if value.nil?
  puts "是nil"
else
  puts "不是nil"
end

if !value
  puts "假值(nil或false)"
end

10.2 链式调用 #

ruby
user = nil

user.profile.avatar

user&.profile&.avatar
user&.dig(:profile, :avatar)

10.3 数组访问 #

ruby
arr = [1, 2, 3]

arr[0]
arr[10]
arr&.[](10)
arr.fetch(10)
arr.fetch(10, nil)

10.4 哈希访问 #

ruby
hash = { a: 1 }

hash[:a]
hash[:b]
hash.fetch(:b)
hash.fetch(:b, nil)

十一、实用示例 #

11.1 安全获取嵌套值 #

ruby
def deep_fetch(hash, *keys)
  keys.reduce(hash) { |h, k| h&.[](k) }
end

data = { user: { profile: { name: "Ruby" } } }
deep_fetch(data, :user, :profile, :name)
deep_fetch(data, :user, :settings, :theme)

11.2 链式默认值 #

ruby
def get_name(params)
  params[:name] ||
    params[:nickname] ||
    params[:username] ||
    "Guest"
end

def get_name_safe(params)
  params[:name].presence ||
    params[:nickname].presence ||
    params[:username].presence ||
    "Guest"
end

11.3 nil安全的转换 #

ruby
class NilSafe
  def self.to_i(value)
    value&.to_i || 0
  end

  def self.to_s(value)
    value&.to_s || ""
  end

  def self.to_f(value)
    value&.to_f || 0.0
  end
end

NilSafe.to_i(nil)
NilSafe.to_s(nil)
NilSafe.to_f(nil)

十二、总结 #

本章我们学习了:

  1. nil特点:NilClass的唯一实例,布尔值为假
  2. nil来源:未初始化变量、越界访问、方法默认返回
  3. nil检查:nil?方法、条件判断、安全导航操作符
  4. nil处理:默认值、fetch、compact、presence
  5. 空对象模式:用对象替代nil
  6. 常见陷阱:链式调用、数组/哈希访问

接下来让我们学习Ruby的数据结构!

最后更新:2026-03-27