ZetCode

Ruby Module 关键字

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

本教程解释了如何使用 Ruby 的 module 关键字。模块在 Ruby 程序中提供命名空间和混入(mixin)功能。

module 关键字定义了方法和常量的命名空间。模块不能像类一样被实例化,但可以被包含(included)在类中。

模块有两个主要用途:命名空间和混入。它们有助于组织代码,并通过混入实现类似多重继承的行为。

基本模块定义

此示例显示了包含常量和方法的最简单的模块定义。模块封装了相关的功能。

basic_module.rb
module Greeter
  DEFAULT_GREETING = "Hello"

  def self.say_hello(name)
    puts "#{DEFAULT_GREETING}, #{name}!"
  end
end

Greeter.say_hello("Alice")
puts Greeter::DEFAULT_GREETING

Greeter 模块包含一个常量和一个模块方法。我们使用 :: 访问常量,使用 . 访问方法。

模块作为命名空间

模块通过充当容器来防止命名冲突。此示例显示了模块如何组织相关类。

namespace.rb
module Animals
  class Dog
    def speak
      puts "Woof!"
    end
  end

  class Cat
    def speak
      puts "Meow!"
    end
  end
end

dog = Animals::Dog.new
cat = Animals::Cat.new

dog.speak
cat.speak

Animals 模块包含 DogCat 类。我们使用模块前缀引用它们,以避免全局命名空间污染。

模块作为混入

可以使用 include 将模块混入类中。这提供了类似多重继承的行为。

mixin.rb
module Debuggable
  def debug_info
    "#{self.class} (id: #{object_id})"
  end
end

class Product
  include Debuggable
end

book = Product.new
puts book.debug_info

Debuggable 模块向任何包含它的类添加 debug_info 方法。这展示了 Ruby 的混入能力。

Extend 与 Include

Ruby 提供了两种混入模块的方式:用于实例方法的 include 和用于类方法的 extend

extend_include.rb
module ClassMethods
  def class_info
    "Class #{self}"
  end
end

module InstanceMethods
  def instance_info
    "Instance of #{self.class}"
  end
end

class Demo
  extend ClassMethods
  include InstanceMethods
end

puts Demo.class_info
puts Demo.new.instance_info

extend 将方法添加到类本身,而 include 将方法添加到实例。这种区别对于正确使用模块至关重要。

模块组合

模块可以包含其他模块,从而实现强大的组合模式。此示例显示了嵌套的模块功能。

composition.rb
module Features
  module Printable
    def print
      puts "Printing #{self}"
    end
  end

  module Serializable
    def serialize
      Marshal.dump(self)
    end
  end
end

class Document
  include Features::Printable
  include Features::Serializable
end

doc = Document.new
doc.print
puts doc.serialize.size

Features 模块包含两个子模块。我们将它们分别包含在 Document 类中以实现模块化功能。

带类方法的模块

这种模式通过使用 self.included 钩子来添加类方法。这是 Ruby 中常见的惯用法。

class_methods.rb
module Tagging
  def self.included(base)
    base.extend(ClassMethods)
  end

  module ClassMethods
    def tags
      @tags ||= []
    end
  end

  def add_tag(tag)
    self.class.tags << tag
  end
end

class Post
  include Tagging
end

post = Post.new
post.add_tag("ruby")
puts Post.tags.inspect

当包含 Tagging 时,它会自动使用 ClassMethods 扩展类。这同时提供了实例方法和类方法。

模块功能隔离

模块可以隔离可能与其他代码冲突的功能。此示例演示了安全的方法添加。

isolation.rb
module MathUtils
  refine Integer do
    def factorial
      (1..self).inject(:*) || 1
    end
  end
end

# Regular Integer has no factorial method
# puts 5.factorial # Would raise NoMethodError

using MathUtils

puts 5.factorial  # Now works: 120

refine 关键字仅在明确使用 using 请求的地方安全地添加方法。这可以避免全局的“猴子补丁”问题。

来源

Ruby 模块文档

本教程介绍了 Ruby 模块,并通过示例展示了命名空间、混入、组合和精炼模式。模块是 Ruby 设计的基础。

作者

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

列出 所有 Ruby 教程