Ruby 有没有办法对类方法和实例方法使用相同的代码?

Ruby 有没有办法对类方法和实例方法使用相同的代码?,ruby,Ruby,有没有办法对类方法和实例方法使用相同的代码 例如,我想做以下工作: Module MyModule def method_in_module puts "hello" end class SomeClass def some_method method_in_module end end end 然后我希望能够做到这一点: SomeClass.method_in_module 还是这个 a = SomeClass.new

有没有办法对类方法和实例方法使用相同的代码

例如,我想做以下工作:

Module MyModule

  def method_in_module
    puts "hello"
  end

  class SomeClass       
    def some_method
      method_in_module
    end
  end
end
然后我希望能够做到这一点:

SomeClass.method_in_module
还是这个

a = SomeClass.new
a.method_in_module

我想我可以有两个方法,一个是self.class\u method\u in_模块,一个是instance\u method\u in_模块,然后将它们包含在类中,在我的实例类中,但是代码是相同的。

您可以使用module.included钩子用模块扩展类

module MyModule
  def self.included(base)
    base.extend MyModule
  end

  def method_in_module
    puts "foo"
  end
end

class SomeClass
  include MyModule
end

SomeClass.new.method_in_module
# => foo
SomeClass.method_in_module
# => foo
必须记住,类和实例具有不同的作用域。因此,在类范围内工作良好的方法可能在类范围内工作不太好

理想情况下,我建议在类级别定义方法,并从实例级别调用类级别的方法


一般来说,我看不出在类级和实例级创建相同方法的模式有什么意义。它有时是有意义的,但要避免生成大量重复的方法。

有多种方法可以实现这一点。一种方法是将类从模块中拉出,然后将模块包括/扩展到类中

module MyModule
  def method_in_module
    puts "hello"
  end
end

class SomeClass
  include MyModule # adds the methods to class instances
  extend MyModule # Adds the methods to the class
end
或者,您也可以使用Ruby中的模块,该模块允许您将方法转发给其他对象

require 'forwardable'

module MyModule
  def self.method_in_module
    puts "hello"
  end

  class SomeClass
    extend Forwardable

    def_delegator :MyModule, :method_in_module

    def self.method_in_module(*args, &block)
      MyModule.method_in_module(*args, &block)
    end

    def some_method
      method_in_module
    end
  end
end
如果您处于Rails上下文中,即使用ActiveSupport,那么您还可以使用与上面的Forwardable变体类似的方法


请注意,这两个变体仅可用于创建实例方法。对于类方法,您仍然需要自己定义方法,如上面的可转发示例所示。

几乎相同是一个重要的关键字。区别是什么?代码是相同的。有时,在实例上也可以使用类方法是有意义的。例如,当您可以在singleton类上设置全局配置设置,然后希望使其在实例上更容易使用时,即为了避免self.class.my_class_方法模式。@Holger我同意,这就是为什么我偶尔编写它是有意义的;但重要的是不要滥用它。当then方法实际上只是一个函数,您不想污染内核使其假装是一个函数时,这是有意义的。我将使用它作为委托/方法重命名方案的一部分。因此,真正的方法将采用目标方法名称和一些参数,执行一点逻辑,然后调用目标方法。我一直在寻找Forwardable,但我喜欢使用rdoc来记录类的想法,我的理解是,这是行不通的。我将尝试这个解决方案-Thanksimone,这意味着包含MyModule的每个类都希望扩展该类。为什么您建议这样做,而不仅仅是将extend MyModule添加到类定义中?RE 1,使MyModule的方法仅可用于SomeClass的单个实例,a=SomeClass.new;a、 扩展MyModule。也许值得注意的是,include和extend可以在def类之外调用:Someclass.extend-MyModule;Someclass.include MyModule。@CarySwoveland include是一个私有方法,只能通过将普通作用域重写为Someclass从外部调用。send:include,MyModule。感谢您的帮助。我知道这是可以延长,所以没有麻烦检查包括。这是一个教训。