如何定义一次方法,但同时将它作为类方法和实例方法

时间:2014-01-01 20:51:18

标签: ruby metaprogramming

有没有办法获取实例方法并将其添加到类中(反之亦然)?

这是我的尝试,但它失败了,因为Ruby不让我将实例方法绑定到类:

#!/usr/bin/env ruby

SOMETHING = :a
class SomeClass
  def some_method(variable, value)
    case SOMETHING
    when :c
      "output for case C"
    when :a, :b
      "output for A or B"
    end
  end
  # here's my failed attampt to add some_method to SomeClass:
  self.instance_method(:some_method).bind(self)
end

# it works as an instance method
bash = SomeClass.new
puts bash.some_method("EDITOR","vim")

# but not as a class method... yet
puts SomeClass.some_method("EDITOR","vim")

错误是“bind参数必须是SomeClass的实例”。换句话说,我无法调用bind(self),因为self 类,而不是类的实例。

1 个答案:

答案 0 :(得分:5)

您可以使用此方法定义一个模块并includeextend您的课程:

使用include定义实例方法,使用extend定义类方法。

MWE:

SOMETHING = :a

module SomeClassMeth
  def some_method(variable, value)
    case SOMETHING
    when :c
      "output for case C"
    when :a, :b
      "output for A or B"
    end
  end
end
class SomeClass
  include SomeClassMeth
  extend SomeClassMeth
end

# it works as an instance method
bash = SomeClass.new
puts bash.some_method("EDITOR","vim")

# but not as a class method... yet
puts SomeClass.some_method("EDITOR","vim")

但是要小心,如果你使用属性:

module SomeClassMeth
  def some_method(variable, value)
      @a
  end
end
class SomeClass
  @a = "@a in class"
  include SomeClassMeth
  extend SomeClassMeth

  def initialize
    @a = "@a in initialize"
  end

end

# it works as an instance method
bash = SomeClass.new
puts bash.some_method("EDITOR","vim")         #@a in initialize

# but not as a class method... yet
puts SomeClass.some_method("EDITOR","vim")  #@a in class