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

发布于 2024-11-06 06:53:21 字数 801 浏览 0 评论 0原文

再次只是为了好玩,但是是否有可能以某种方式获取包含方法定义的块并将它们添加到对象中?以下内容不起作用(我从没想过它会起作用),但只是为了让您了解我正在玩什么。

我确实知道我可以使用 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...

Just for fun, again, but is it possible to take a block that contains method definitions 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...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

夜夜流光相皎洁 2024-11-13 06:53:21

您可以使用 class_eval(也可以别名为 module_eval) 或 < code>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!

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!
極樂鬼 2024-11-13 06:53:21

是的,

我怀疑您想到了这一点,并且正在寻找一些其他方式,但以防万一......

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

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

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文