ZetCode

Ruby defined? 操作符

最后修改日期:2025 年 4 月 27 日

本教程解释了如何使用Ruby的defined?操作符。它会检查一个变量、方法或表达式是否已定义,并返回其类型。

defined?操作符是一个特殊的关键字,用于测试Ruby实体的存在。如果找到,它会返回一个描述其类型的字符串;如果未定义,则返回nil。

此操作符通过在使用前安全地检查定义来帮助防止错误。它适用于变量、方法、常量和其他Ruby语言元素。

基本变量检查

此示例展示了如何检查局部变量、实例变量和全局变量是否存在。defined?操作符为每种类型返回不同的字符串。

basic_variables.rb
local_var = 10
@instance_var = 20
$global_var = 30

puts defined?(local_var)    # "local-variable"
puts defined?(@instance_var) # "instance-variable"
puts defined?($global_var)   # "global-variable"
puts defined?(unknown_var)   # nil

该操作符为已定义的变量返回描述性字符串,为未定义的变量返回nil。这有助于区分变量类型和状态。

检查方法是否存在

defined?操作符可以验证方法是否可用。它会检查内置方法和用户定义的方法。

method_checking.rb
def greet
  "Hello"
end

puts defined?(greet)       # "method"
puts defined?(puts)        # "method"
puts defined?(unknown_method) # nil

# With parameters
puts defined?(greet())     # "method"

该操作符为所有已定义的方法(包括Ruby核心方法)返回“method”。括号是可选的,但可以使方法检查更清晰。

常量验证

Ruby中的常量与变量的行为不同。defined?操作符有助于在访问常量之前检查其是否存在。

constant_checking.rb
PI = 3.1415
module MyModule
  VERSION = "1.0"
end

puts defined?(PI)              # "constant"
puts defined?(MyModule::VERSION) # "constant"
puts defined?(UNKNOWN_CONST)   # nil

嵌套的常量必须用其模块进行完全限定。该操作符无论作用域如何,都为已定义的常量返回“constant”。

检查表达式

defined?操作符可以测试整个表达式,而不仅仅是简单的标识符。这有助于在执行前验证复杂的操作。

expression_checking.rb
x = 10
y = 20

puts defined?(x + y)      # "method"
puts defined?(x.foo)      # nil
puts defined?(x.methods)  # "method"
puts defined?(x[0])       # nil

数学运算返回“method”,因为它们使用了+方法。未定义的运算返回nil。这有助于防止NoMethodError异常。

父类方法检查

在使用继承时,defined?可以检查父类是否实现了某个方法。这对于方法覆盖场景很有用。

superclass_checking.rb
class Parent
  def inherited_method
    "Parent method"
  end
end

class Child < Parent
  def inherited_method
    if defined?(super)
      super + " extended"
    else
      "No parent method"
    end
  end
end

puts Child.new.inherited_method # "Parent method extended"

该示例在调用父类方法之前安全地检查其实现。当父类可能未定义该方法时,这种模式可以防止错误。

条件赋值

defined?与条件逻辑结合使用可以安全地初始化变量。这可以防止重新初始化已存在的变量。

conditional_assignment.rb
$counter ||= 0

unless defined?($counter)
  $counter = 0
end

def increment
  $counter += 1
end

increment
puts $counter # 1

这两种模式都确保在使用变量之前它们已经存在。与 ||= 不同,defined?版本更明确,并且可以处理nil/false值。

检查yield和块

该操作符可以使用yield测试是否将块传递给了方法。这有助于使方法成为可选块。

yield_checking.rb
def process
  if defined?(yield)
    yield
  else
    "No block given"
  end
end

puts process { "Block provided" } # "Block provided"
puts process                      # "No block given"

该方法根据块的存在调整其行为。这创建了更灵活的API,可以带块或不带块工作。

来源

Ruby 关键字文档

本教程涵盖了Ruby的defined?操作符,并提供了实用的示例,展示了变量、方法和表达式的检查模式。

作者

我叫Jan Bodnar,是一名热情的程序员,拥有丰富的编程经验。我自2007年起就一直在撰写编程文章。迄今为止,我已撰写了1400多篇文章和8本电子书。我在编程教学方面有十多年的经验。

列出 所有 Ruby 教程