method vs. def
As a programming exercise, I've written a Ruby snippet that creates a class, instantiates two objects from that class, monkeypatches one object, and relies on method_missing to monkeypatch the other one.
Here's the deal. This works as intended:
class Monkey
def chatter
puts "I am a chattering monkey!"
end
def method_missing(m)
puts "No #{m}, so I'll make one..."
def screech
puts "This is the new screech."
end
end
end
m1 = Monkey.new
m2 = Monkey.new
m1.chatter
m2.chatter
def m1.screech
puts "Aaaaaargh!"
end
m1.screech
m2.screech
m2.screech
m1.screech
m2.screech
You'll notice that I have a parameter for method_missing. I did this because I was hoping to use define_method to dynamically create missing methods with the appropriate name. However, it doesn't work. In fact, even using define_method with a static name like so:
def method_missing(m)
puts "No #{m}, so I'll make one..."
define_method(:screech) do
puts "This is the new screech."
end
end
Ends with the following result:
ArgumentError: wrong number of arguments (2 for 1)
method method_missing in untitled document at line 9
method method_missing in untitled document at line 9
at top level in untitled document at line 26
Program exited.
What makes the error message more bewildering is that I only have one argument for method_missing
...
define_method
is a (private) method of the object Class. You are calling it from an instance. There is no instance method called define_method
, so it recurses to your method_missing
, this time with :define_method
(the name of the missing method), and :screech
(the sole argument you passed to define_method
).
Try this instead (to define the new method on all Monkey objects):
def method_missing(m)
puts "No #{m}, so I'll make one..."
self.class.send(:define_method, :screech) do
puts "This is the new screech."
end
end
Or this (to define it only on the object it is called upon, using the object's "eigenclass"):
def method_missing(m)
puts "No #{m}, so I'll make one..."
class << self
define_method(:screech) do
puts "This is the new screech."
end
end
end
self.class.define_method(:screech)不起作用,因为define_method是你可以做的私有方法
class << self
public :define_method
end
def method_missing(m)
puts "No #{m}, so I'll make one..."
Monkey.define_method(:screech) do
puts "This is the new screech."
end
def method_missing(m)
self.class.class_exec do
define_method(:screech) {puts "This is the new screech."}
end
end
所有Monkey对象都可以使用尖叫方法。
链接地址: http://www.djcxy.com/p/25760.html上一篇: 获取当前正在执行的方法的名称
下一篇: 方法与def