0

我怎样才能使这段代码工作?

class Meta

    @array = [:a,:b]

    def self.method_missing(name, *args, &block)
            if @array.include? name
                    self.class.send(:define_method, name) do
                            do_call(name)
                    end
            else
                    puts "[#{name.inspect}] is not part of array!"
            end
    end

    def do_call arg
            puts "doing call for ['#{arg}'] "
    end
end

这个想法是让 Meta.a(在被定义之后)拥有

def a 
 do_call(a)
end

在它的身体里。但是运行这个之后,我的输出是:

[:do_call] 不是数组的一部分!

更新:现在有点像这样工作:

class Meta

    @array = [:a,:b]

    def self.do_call arg
            puts "doing call for ['#{arg}'] "
    end

    def self.method_missing(name, *args, &block)
            puts "#{name} is missing!"
            if @array.include? name
                    self.class.send(:define_method, name) do
                            do_call name
            end
            else
                    puts "[#{name.inspect}] is not part of array!"
            end
       end
    end

但是,这里是 IRB 会话的摘录:

[~/code] $ irb -r 元

irb(main):001:0> Meta.a

一个不见了!

=> #

irb(main):002:0> Meta.a

正在调用 ['a']

=> 无

irb(main):003:0> c = Meta.new

=> #

irb(主):004:0> ca

NoMethodError:未定义的方法“a”用于#

    from (irb):4

irb(main):005:0> Meta.methods

=> [“检查”,“发送”,“pretty_inspect”,“class_eval”,“克隆”,“yaml_tag_read_class”,> >“public_methods”,“protected_instance_methods”,“发送", "private_method_defined?", "equal?", "freeze", "do_call", "yaml_as", "methods", "instance_eval", "to_yaml", "display", "dup", "object_id", "include ?”、“private_instance_methods”、“instance_variables”、“扩展”、“protected_method_defined?”、“const_defined?”、“to_yaml_style”、“instance_of?”、“eql?”、“name”、“public_class_method”、“hash” , “id”, “new”, “singleton_methods”, “yaml_tag_subclasses?”, “pretty_print_cycle”, “taint”, “pretty_print_inspect”, “frozen?”, “instance_variable_get”, “autoload”,“constants”、“kind_of?”、“to_yaml_properties”、“to_a”、“ancestors”、“private_class_method”、“const_missing”、“type”、“yaml_tag_class_name”、“instance_method”、“<”、“protected_methods”、“ <=>”、“instance_methods”、“==”、“method_missing”、“method_defined?”、“超类”、“>”、“pretty_print”、“===”、“instance_variable_set”、“const_get”、“ is_a?", "taguri", ">=", "respond_to?", "to_s", "<=", "module_eval", "class_variables", "allocate", "class", "taguri=", "pretty_print_instance_variables”、“污染?”、“public_instance_methods”、“=~”、“private_methods”、“public_method_defined?”、“自动加载?”、“id "、"nil?"、"untaint"、"included_modules"、"const_set"、"a"、"method"]

是什么赋予了?'a' 是一个类方法,它不会传递给新的 Meta 对象 (c)。为什么?

4

1 回答 1

4

您将 do_call 定义为实例方法,而您可能打算将其定义为类方法。这就是为什么它也为 do_call 调用 method_missing 并且你得到了你得到的错误。

另请注意,当您这样做时self.class.sendself.class将是 Class,因此该方法将在所有类上可用,而不仅仅是 meta。您可能更想要:

class <<self
  self
end.send

编辑以响应您的更新:

'a' 是一个类方法,它不会传递给新的 Meta 对象 (c)。为什么?

因为a是类方法[1]。类的实例只获取类的实例方法。

您将 a 定义为 Class 上的实例方法,然后尝试在 Meta 的实例上调用它,这不起作用。在 Class 的 ruby​​ 实例方法以及类上定义的单例方法中,只能通过doing调用TheClass.the_method,而不是instance_of_the_class.the_method。如果要在 Meta 的实例上调用方法,请将其定义为实例方法。如果你想Meta.a做得好,Meta.new.a你必须同时定义一个实例和一个类方法a

[1] 实际上,正如我已经说过的,您定义它的方式甚至不是 Meta 的类方法。它是 Class 的一个实例方法(这意味着您也可以将其称为 String.a)。

于 2009-09-07T17:17:33.043 回答