Ruby 如何声明mixin方法,使其';实例方法和类方法都可用吗?
我想在Ruby模块中放置一个方法,这样就可以使用简单的语法从类方法或实例方法调用它:Ruby 如何声明mixin方法,使其';实例方法和类方法都可用吗?,ruby,module,mixins,Ruby,Module,Mixins,我想在Ruby模块中放置一个方法,这样就可以使用简单的语法从类方法或实例方法调用它: module MyMod def fmt *args args.map { | a | "You said #{a}" } end end class MyClass include MyMod def inst puts fmt 1,2,3 end def self.cls puts fmt 4,5,6 end end 上述方法不起作用,因为类方法(cl
module MyMod
def fmt *args
args.map { | a | "You said #{a}" }
end
end
class MyClass
include MyMod
def inst
puts fmt 1,2,3
end
def self.cls
puts fmt 4,5,6
end
end
上述方法不起作用,因为类方法(cls
)无法看到实例方法fmt。如果我将定义更改为self.fmt
,那么实例方法必须将其作为MyMod.fmt
调用
我希望能够从这两种方法中调用fmt(一些东西)
。有没有“红宝石般”的方法?我可以将模块定义为
module MyMod
def self.fmt *args
args.map { | a | "You said #{a}" }
end
def fmt *args
MyMod.fmt args
end
end
但那不是很干,是吗?有一种更简单的方法吗?
包括和扩展MyClass
中的MyMod
模块,以便fmt
方法作为实例和类方法添加到MyClass
Object#extend
所做的是将模块的方法添加到单个实例中。在这种情况下,该实例就是类本身,这就是为什么这些方法可以作为类方法使用。您可以使用Module#included
方法的优点来这样做:
module MyMod
# here base is a class the module is included into
def self.included(base)
# extend includes all methods of the module as class methods
# into the target class
base.extend self
end
def fmt(*args)
args.map { |a| "You said #{a}" }
end
end
class MyClass
# regular include provides us with instance methods
# and defined above MyMod#included hook - with class methods
include MyMod
def inst
puts fmt(1, 2, 3)
end
def self.cls
puts fmt(4, 5, 6)
end
end
puts MyClass.cls
puts MyClass.new.inst
以下是输出:
You said 4
You said 5
You said 6
You said 1
You said 2
You said 3
要获得更详细的解释,请看。当构建某种充当DSL的东西时,回调是很好的,其他开发人员应该将其包含到他们的类中。否则,这有点太神奇了,无法证明其合理性,因为使用include
是否会导致添加类方法还不是很清楚。因此,如果这是在内部代码中,那么手动使用extend
本身几乎总是有好处的,而不是麻烦地记录这种特殊行为。这一点很好,但是如果你想在多个地方使用这个模块,我不认为在你需要的地方调用include
和extend
都是一个很好的解决方案。@KL-7,为什么不呢?模块正在为您做这件事。。。你不必这么做。不管怎样,这是唯一的方法。这正是我们正在讨论的,模块是否应该“为你做那件事”。而且这是“唯一的方法”显然是错误的,因为仍然有“手动”方法……完全没有听到第一条评论,对不起;)