3

クラスのインスタンスのメソッドを以下のように委譲するA$delegation_target:

$delegation_target = ""
class A
  def method_missing *args, ≺ $delegation_target.send(*args, &pr) end
  def respond_to_missing? *args; $delegation_target.respond_to?(*args) end
end

のメソッドの に関係なく、 return のarityインスタンスのメソッドAの:-1arity$delegation_target

def $delegation_target.foo; end
A.new.method(:foo).arity # => -1

def $delegation_target.foo arg1; end
A.new.method(:foo).arity # => -1

def $delegation_target.foo arg1, arg2; end
A.new.method(:foo).arity # => -1

def $delegation_target.foo arg1, arg2, arg3; end
A.new.method(:foo).arity # => -1

これはどこ-1から来たのですか?そして、可能なメソッド namemに対して、(定義されている場合)A.new.method(m).arityのアリティを返すようにする方法はありますか?$delegation_target.method(m)

4

2 に答える 2

6

Object#methodrespond_to_missing?&method_missingを特別な方法で処理します。Ruby C ソースに飛び込んで、何が起こるか見てみましょう。

から始めてObject#method、 を呼び出します。これは、呼び出されたオブジェクトと渡された id のmnew新しいMethodオブジェクトを作成します。のソースでmnewは、メソッドが定義されていない場合の特別な処理を簡単に確認できますが、id が指定された場合respond_to_missing?は戻ります。true

if (UNDEFINED_METHOD_ENTRY_P(me)) {
    ID rmiss = rb_intern("respond_to_missing?");
    VALUE sym = ID2SYM(id);

    if (obj != Qundef && !rb_method_basic_definition_p(klass, rmiss)) {
        if (RTEST(rb_funcall(obj, rmiss, 2, sym, scope ? Qfalse : Qtrue))) {
            def = ALLOC(rb_method_definition_t);
            def->type = VM_METHOD_TYPE_MISSING;
            def->original_id = id;
            // ...

def->type = VM_METHOD_TYPE_MISSING;が重要です。の定義をVM_METHOD_TYPE_MISSING見つけると、それが「 のラッパー」であることがわかりますmethod_missing(id)。したがって、本質的に返されるメソッドは実際にはただmethod_missingのものであり、最初の引数は最初に取得しようとしていたメソッドの ID として既に指定されています。

method_missingのアリティが取得したものと同じであることを確認することで、疑いを確認できます。

A.new.method(:method_missing).arity  #=> -1

余談ですが、アリティオブは-1、メソッドが無制限の数の引数を取ることができることを意味します。

呼び出されているメソッドの「実際の」アリティを返すことができるかどうかについては…いいえ、できません。1 つには、Ruby は で何が起こるかについて何も仮定method_missingせず、単に他のメソッドに委譲していることさえ知りません。

于 2012-12-09T17:59:32.740 に答える
3

負のアリティは、* で始まる引数が最後にあることを意味します。1 つの必須引数の後に * の接頭辞が付いた引数がある場合 (つまり、1 つの必須引数とオプションの追加量)、アリティは -2 として表されるため、n は必須引数の数である -n-1 になります。

-n-1 は n の 1 の補数として知られており、ruby には必要な引数の数を取得する演算子、演算子さえあります~

p ~A.new.method(:foo).arity #=> 0
于 2012-12-09T17:58:18.233 に答える