Trầ*_* Dự 2 ruby metaprogramming
例如,我有以下自定义类和模块:
module SimpleModule
def hello_world
puts 'i am a SimpleModule method'
end
def self.class_hello_world
puts 'i am a SimpleModule class method'
end
end
class SimpleClass
def hello_world
puts 'i am SimpleClass method'
end
def self.class_hello_world
puts 'i am a SimpleClass class method'
end
end
Run Code Online (Sandbox Code Playgroud)
我尝试使用方法在类和模块中调用这些方法 send
SimpleClass.send(class_hello_world) # work
SimpleClass.new.send(hello_world) # work
SimpleModule.send(class_hello_world) # work
SimpleModule.new.send(hello_world) # not work
SimpleModule.send(hello_world) # not work
Run Code Online (Sandbox Code Playgroud)
换句话说,我不知道如何调用hello_world从SimpleModule.如果该方法之前使用self定义,则可能.
我需要这样做,因为我想实现一个"自定义包含":包括从模块到另一个类的所有方法.
请告诉我怎么做.
五个陈述
让我们一次一个地考虑这五个陈述(但是以与呈现的顺序不同的顺序).请注意,send参数必须是表示为字符串或符号的方法的名称.
SimpleModule.send("class_hello_world")
# i am a SimpleModule class method
Run Code Online (Sandbox Code Playgroud)
这是正常的,尽管这种方法通常称为模块方法.一些常见的内置模块(如Math)仅包含模块方法.
SimpleClass.send(:class_hello_world)
# i am a SimpleClass class method
Run Code Online (Sandbox Code Playgroud)
由于类是模块,因此行为与上述相同.class_hello_world通常被称为类方法.
SimpleClass.new.send(:hello_world)
# i am SimpleClass method
Run Code Online (Sandbox Code Playgroud)
这是实例方法的正常调用.
SimpleModule.send("hello_world")
#=> NoMethodError: undefined method `hello_world' for SimpleModule:Module
Run Code Online (Sandbox Code Playgroud)
没有模块方法hello_world.
SimpleModule.new.send(hello_world)
#=> NoMethodError: undefined method `new' for SimpleModule:Module
Run Code Online (Sandbox Code Playgroud)
无法创建模块的实例.
include VS prepend
假设有人写道
SimpleClass.include SimpleModule
#=> SimpleClass
SimpleClass.new.hello_world
# i am SimpleClass method
Run Code Online (Sandbox Code Playgroud)
所以SimpleClass'原始方法hello_world不会被模块的方法用同名的方法覆盖.考虑一下SimpleClass'祖先.
SimpleClass.ancestors
#=> [SimpleClass, SimpleModule, Object, Kernel, BasicObject]
Run Code Online (Sandbox Code Playgroud)
红宝石将寻找hello_world在SimpleClass--and找到它-考虑之前SimpleModule.
但是,可以使用Module#prepend放在SimpleModule#hello_world之前SimpleClass#hello_world.
SimpleClass.prepend SimpleModule
#=> SimpleClass
SimpleClass.new.hello_world
# i am a SimpleModule method
SimpleClass.ancestors
#=> [SimpleModule, SimpleClass, Object, Kernel, BasicObject]
Run Code Online (Sandbox Code Playgroud)
绑定未绑定的方法
还有一件事你做.SimpleModule实例方法(这里只有一个)是未绑定的.您可以使用UnboundMethod#bind将每个绑定到一个实例,SimpleClass然后使用call或执行它send.
sc = SimpleClass.new
#=> #<SimpleClass:0x007fcbc2046010>
um = SimpleModule.instance_method(:hello_world)
#=> #<UnboundMethod: SimpleModule#hello_world>
bm = um.bind(sc)
#=> #<Method: SimpleModule#hello_world>
bm.call
#=> i am a SimpleModule method
sc.send(:hello_world)
#=> i am a SimpleModule method
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
270 次 |
| 最近记录: |