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 セッションの抜粋を次に示します。

[~/コード] $ irb -r メタ

irb (メイン):001:0> Meta.a

がありません!

=> #

irb (メイン):002:0> Meta.a

['a'] の呼び出しを行っています

=>なし

irb (メイン):003:0> c = Meta.new

=> #

irb (メイン):004:0> ca

NoMethodError: 未定義のメソッド `a' #

    from (irb):4

irb (メイン):005:0> Meta.methods

=> ["inspect", "send", "pretty_inspect", "class_eval", "clone", "yaml_tag_read_class", > >"public_methods", "protected_instance_methods", " send"、"private_method_defined?"、"equal?"、"freeze"、"do_call"、"yaml_as"、"methods"、"instance_eval"、"to_yaml"、"display"、"dup"、"object_id"、"include ?"、"private_instance_methods"、"instance_variables"、"extend"、"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?", "superclass", ">", "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", "tainted?", "public_instance_methods", "=~", "private_methods", "public_method_defined?", "autoload?","id ", "nil?", "untaint", "included_modules", "const_set", "a", "method"]

何が与えますか?'a' はクラス メソッドであり、新しい Meta オブジェクト (c) には渡されません。なんで?

4

1 に答える 1

4

do_call をインスタンス メソッドとして定義しましたが、おそらくそれをクラス メソッドとして定義するつもりでした。これが、do_call に対しても method_missing を呼び出し、エラーが発生する理由です。

self.class.sendまた、実行self.classするとクラスになるため、メソッドはメタだけでなくすべてのクラスで使用できることに注意してください。あなたはおそらくむしろ欲しい:

class <<self
  self
end.send

更新に応じて編集します。

'a' はクラス メソッドであり、新しい Meta オブジェクト (c) には渡されません。なんで?

aクラスメソッドだから[1] 。クラスのインスタンスは、クラスのインスタンス メソッドのみを取得します。

Class のインスタンス メソッドとして a を定義し、それを Meta のインスタンスで呼び出そうとしましたが、機能しません。ルビーでは Class のインスタンスメソッドやクラスに定義されたシングルトンメソッドは do でしか呼び出せず、 で呼び出せ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 に答える