只是为了好玩 - 通过块添加方法到对象

时间:2011-05-12 04:56:17

标签: ruby anonymous-class

再次,只是为了好玩,但是可以采用包含方法定义的块并将其添加到对象中吗?以下不起作用(我从未预料到),但只是让你了解我正在玩的东西。

我知道我可以用class << existing_object重新打开一个类并以这种方式添加方法,但代码是否有办法在块中传递该信息?

我想我想在这里借一点Java思想。

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

编辑|这是上面的工作版本,基于edgerunner的答案:

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

2 个答案:

答案 0 :(得分:4)

您可以使用class_eval(也称为module_eval)或instance_eval来分别评估类/模块或对象实例的上下文中的块。

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!

答案 1 :(得分:2)

我怀疑你是否想过这个并且正在寻找一些其他方式,但以防万一......

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

对于记录,这不是动态添加方法的常用方法。通常,动态方法以块本身的形式开始生命,例如,参见*Module#define_method*.