动态定义实例方法,但不定义类方法

时间:2012-12-01 23:35:02

标签: ruby metaprogramming

Ruby 1.9.3:我正在尝试实现一个方法,该方法将类,符号和proc作为参数,并为该类定义(最终覆盖)新的实例方法,但一个类方法,以便该测试应该通过:

require 'test/unit'

include Test::Unit::Assertions

class String
  def my_method
    'my_method'
  end
end

def define_instance_method(klass, method, &block)
  # klass.send :define_method, method, &block
  # ...
end

define_instance_method(Object, :my_method) { 'define_instance_method my_method' }
define_instance_method(String, :my_method) { 'define_instance_method my_method' }

assert Object.new.my_method == 'define_instance_method my_method'
assert_raise(NoMethodError) { Object.my_method }

assert String.new.my_method == 'define_instance_method my_method'
assert_raise(NoMethodError) { String.my_method }

我做了很多尝试(define_methoddefine_singleton_methodclass_evalinstance_evalinstance_execmodule_eval ......)但没有成功;你有什么想法吗?

2 个答案:

答案 0 :(得分:3)

@ProGNOMmers,回想一下Ruby中的对象是类,类是对象。

所以Ruby中的所有东西都是对象,甚至是类:)

当您在Object中定义方法时,Class以及从Object继承的任何类也可以使用它。

这对所有班级都有意义。

一些证据:

define_instance_method(String, :my_method) { 'define_instance_method my_method' }

p String.new.my_method
p String.my_method

# =>  "define_instance_method my_method"
# =>  stackoverflow.rb:11:in `<main>': undefined method `my_method' for String:Class (NoMethodError)

请参阅Object中尚未定义的方法,因此在String内无法使用。

现在让我们这样做:

define_instance_method(Object, :my_method) { 'define_instance_method my_method' }

p String.my_method
# => "define_instance_method my_method"

p Array.my_method
# => "define_instance_method my_method"

p NilClass.my_method
# => "define_instance_method my_method"

所以只需在测试中评论define_instance_method(Object... 并且String规格将很好地通过。

Here are some crash tests

答案 1 :(得分:0)

class_eval应该适合你。让我知道为什么它不适合你

class A
end

A.class_eval do
  define_method(:foo) {puts 'hello'}
end

A.new.foo #hello
A.foo     #NoMethodError: undefined method `foo' for A:Class