【发布时间】:2026-01-05 19:55:01
【问题描述】:
a1 是A 上的一个方法。
module A
def self.a1
puts "I am defined in A"
end
end
class Sample
include A
end
samp = Sample.new
如何拨打samp.a1?
puts samp.a1
【问题讨论】:
a1 是A 上的一个方法。
module A
def self.a1
puts "I am defined in A"
end
end
class Sample
include A
end
samp = Sample.new
如何拨打samp.a1?
puts samp.a1
【问题讨论】:
这里有几件事要记住:
self 前缀的模块方法,这意味着它们可以直接在模块上调用,例如 A.a1,但这也意味着它们不会被导入与include。那些没有 self 声明的是“混合方法”,或者那些将在include 上自动导入的方法。include 多个模块定义了一个方法,那么最后包含的模块将是实际被调用的模块。这里的解决方法是将def self.a1 中的def a1 更改为module A,或者直接使用A.a1 调用它。如果 B 还定义了a1,那么它将具有优先级除非您首先include B,使其优先级较低。
【讨论】:
include 使 mixin 成为超类。就是这样。关于 Ruby 混合,实际上没有什么需要了解的了。这只是标准无聊的旧继承。
include,您可以随时任意添加额外的“超类”类型继承。起初这似乎很奇怪,就像您如何也可以对单个对象执行此操作一样。
如果您知道这种事情会提前发生,您可以在包含模块时使用别名(请注意,这会将方法定义从 def self.a1 更改为 def a1,以便它们被正确包含为实例方法):
module A
def a1
puts "I am defined in A"
end
end
module B
def a1
puts "I am defined in B"
end
end
class Sample
include A
alias :a_a1 :a1
include B
alias :b_a1 :a1
end
samp = Sample.new
samp.a_a1
samp.b_a1
samp.a1
运行此输出:
I am defined in A
I am defined in B
I am defined in B
不过,作为一般规则,如果可以的话,我会避免这种情况并重命名模块中的一个方法;尽管有时您出于某种原因无法做到这一点。
【讨论】:
如果它只是用于 a1,那么这应该可以工作:
class Sample
include A
def a1
self.class.a1
end
end
如果所有方法都需要它,您可以尝试使用类的发送命令捕获 NoMethodError,但这通常是多余的。
【讨论】:
include - 您需要改为extend。