Just for fun, again, but is it possible to take a block that contains method definiti开发者_运维问答ons and add those to an object, somehow? The following doesn't work (I never expected it to), but just so you get the idea of what I'm playing around with.
I do know that I can reopen a class with class << existing_object
and add methods that way, but is there a way for code to pass that information in a block?
I guess I'm trying to borrow a little Java thinking here.
def new(cls)
obj = cls.new
class << obj
yield
end
obj
end
class Cat
def meow
puts "Meow"
end
end
cat = new(Cat) {
def purr
puts "Prrrr..."
end
}
cat.meow
# => Meow
# Not working
cat.purr
# => Prrrr...
EDIT | Here's the working version of the above, based on edgerunner's answer:
def new(cls, &block)
obj = cls.new
obj.instance_eval(&block)
obj
end
class Cat
def meow
puts "Meow"
end
end
cat = new(Cat) {
def purr
puts "Prrrr..."
end
}
cat.meow
# => Meow
cat.purr
# => Prrrr...
You can use class_eval
(also aliased as module_eval
) or instance_eval
to evaluate a block in the context of a class/module or an object instance respectively.
class Cat
def meow
puts "Meow"
end
end
Cat.module_eval do
def purr
puts "Purr"
end
end
kitty = Cat.new
kitty.meow #=> Meow
kitty.purr #=> Purr
kitty.instance_eval do
def purr
puts "Purrrrrrrrrr!"
end
end
kitty.purr #=> Purrrrrrrrrr!
Yes
I suspect you thought of this and were looking for some other way, but just in case...
class A
def initialize
yield self
end
end
o = A.new do |o|
class << o
def purr
puts 'purr...'
end
end
end
o.purr
=> purr...
For the record, this isn't the usual way to dynamically add a method. Typically, a dynamic method starts life as a block itself, see, for example, *Module#define_method*.
精彩评论