Ruby 模块(Module)
在 Ruby 中,模块(Module) 是一种组织代码和共享功能的方式,类似于类,但不能被实例化。模块主要用于实现代码复用、命名空间管理以及混入(Mixin)功能。以下是对 Ruby 模块的中文讲解,涵盖定义、使用、混入等关键内容,力求简洁清晰。
1. 什么是模块?
模块是一组方法、常量和其他模块或类的集合,定义在 module
和 end
之间。模块不能创建对象,也不能继承,但可以通过混入(include
或 extend
)将功能添加到类或对象中。
# 语法
module 模块名
# 方法、常量等
end
模块名:通常首字母大写,遵循 CamelCase 命名。
2. 模块的用途
模块有三大主要用途:
- 命名空间:避免命名冲突,组织相关代码。
- 混入(Mixin):将模块的方法混入类,共享功能。
- 定义工具方法:存储静态方法或常量。
3. 模块的定义与使用
基本定义
module Greetings
def say_hello
puts "Hello!"
end
end
说明:模块中的方法默认是实例方法,需混入类才能使用。
作为命名空间
模块可以组织代码,防止方法或常量名冲突。
module MathUtils
PI = 3.14159
def self.square(num)
num * num
end
end
puts MathUtils::PI # 输出:3.14159
puts MathUtils.square(4) # 输出:16
说明:
- 使用
::
访问模块中的常量或方法。 self.
定义模块的静态方法(类方法),可直接调用。
4. 混入(Mixin)
模块通过 include
或 extend
混入类或对象,提供方法复用。
使用 include
include
将模块的实例方法混入类,供类的实例调用。
module Greetings
def say_hello
puts "Hello, #{self.name}!"
end
end
class Person
include Greetings
attr_accessor :name
end
person = Person.new
person.name = "Alice"
person.say_hello # 输出:Hello, Alice!
使用 extend
extend
将模块的实例方法作为类的类方法(静态方法)。
module Greetings
def say_hello
puts "Hello from class!"
end
end
class Person
extend Greetings
end
Person.say_hello # 输出:Hello from class!
include vs extend
include
:模块方法成为类的实例方法。extend
:模块方法成为类的类方法。
混入多个模块
类可以混入多个模块,方法按后混入优先(类似继承链)。
module A
def test
puts "From A"
end
end
module B
def test
puts "From B"
end
end
class MyClass
include A
include B
end
MyClass.new.test # 输出:From B(B 后混入,优先级更高)
5. 模块中的常量
模块可以定义常量,通过 ::
访问。
module Config
VERSION = "1.0.0"
end
puts Config::VERSION # 输出:1.0.0
6. 模块的嵌套
模块可以嵌套定义,用于更细致的组织。
module Outer
module Inner
def self.say
puts "Hello from Inner"
end
end
end
Outer::Inner.say # 输出:Hello from Inner
7. 模块与类的区别
- 模块:不能实例化,无继承关系,主要用于混入和命名空间。
- 类:可实例化,支持继承,用于创建对象。
- 模块和类都可以定义方法和常量,但模块更轻量,专注于功能共享。
8. 常见内置模块
Ruby 提供了一些内置模块,常用于混入:
- Comparable:提供比较运算符(如
<
,>
),需定义<=>
方法。
class Person
include Comparable
attr_accessor :age
def initialize(age)
@age = age
end
def <=>(other)
@age <=> other.age
end
end
p1 = Person.new(25)
p2 = Person.new(30)
puts p1 < p2 # 输出:true
- Enumerable:提供迭代方法(如
map
,select
),需定义each
方法。
class MyList
include Enumerable
def initialize(*items)
@items = items
end
def each
@items.each { |item| yield item }
end
end
list = MyList.new(1, 2, 3)
puts list.map { |x| x * 2 } # 输出:[2, 4, 6]
9. 模块方法的作用域
- 实例方法:通过
include
混入后,供实例调用。 - 模块方法(静态方法):定义时加
self.
,直接通过模块调用。 - 私有方法:用
private
定义,仅模块内部或混入后内部使用。
module Utils
private
def secret
"Hidden"
end
end
10. 注意事项
- 模块不可实例化:不能用
new
创建模块对象。 - 方法冲突:多个模块混入时,后混入的优先级更高。
- 作用域:模块中的方法和常量可以通过
::
或混入访问。 - 灵活性:模块是 Ruby 实现多重继承效果的主要方式(通过 Mixin)。
- 命名规范:模块名首字母大写,避免与类名冲突。
11. 示例:综合应用
module Loggable
def log(message)
puts "[LOG] #{message}"
end
end
module Nameable
attr_accessor :name
def greet
puts "Hello, #{name}!"
end
end
class User
include Loggable
include Nameable
end
user = User.new
user.name = "Bob"
user.greet # 输出:Hello, Bob!
user.log("Login") # 输出:[LOG] Login
总结
Ruby 模块是组织代码和共享功能的核心工具,通过命名空间避免冲突,通过混入(Mixin)实现方法复用。include
和 extend
是模块的主要使用方式,结合内置模块如 Comparable
和 Enumerable
,可以大幅提升代码灵活性和可读性。
如果你有具体问题或需要更详细的示例,请告诉我!