开发者

Just for fun - add methods to an object via a block

开发者 https://www.devze.com 2023-03-05 12:41 出处:网络
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 ju

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*.

0

精彩评论

暂无评论...
验证码 换一张
取 消