ico*_*ast 0 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")
Run Code Online (Sandbox Code Playgroud)
错误是"bind参数必须是SomeClass的实例".换句话说,我不能调用bind(self)因为self 是类而不是类的实例.
你可以用这个方法定义一个模块,include然后extend你的类:
在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")
Run Code Online (Sandbox Code Playgroud)
但是要小心,如果你使用属性:
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
Run Code Online (Sandbox Code Playgroud)