如何声明一个mixin方法,使它可以从实例方法和类方法中使用?

Cod*_*rer 2 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
Run Code Online (Sandbox Code Playgroud)

上面的方法不起作用,因为类method(cls)无法看到实例方法fmt.如果我将定义更改为self.fmt,则实例方法必须将其作为调用MyMod.fmt.

我希望能够fmt (some stuff)从这两种方法中调用.这样做有"ruby-ish"方式吗?我可以将模块定义为

module MyMod
  def self.fmt *args
    args.map { | a | "You said #{a}" }
  end
  def fmt *args
    MyMod.fmt args
  end
end
Run Code Online (Sandbox Code Playgroud)

但那不是很干,是吗?有更简单的方法吗?

KL-*_*L-7 5

你可以利用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
Run Code Online (Sandbox Code Playgroud)

这是输出:

You said 4
You said 5
You said 6

You said 1
You said 2
You said 3
Run Code Online (Sandbox Code Playgroud)

有关更详细的说明,请查看本文.