当我将类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
endA实例上的方法的arity返回-1,而与$delegation_target上的方法的arity无关
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是从哪里来的?还有,有没有办法使得对于任何可能的方法名m,A.new.method(m).arity都会返回$delegation_target.method(m)的any (如果已定义)?
发布于 2012-12-10 01:59:33
Object#method以一种特殊的方式处理respond_to_missing? & method_missing。让我们深入研究Ruby C源代码,看看会发生什么:
从Object#method开始,我们调用mnew,它为被调用的对象和传递的id创建一个新的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;很重要。找到definition for VM_METHOD_TYPE_MISSING,我们看到它是一个“method_missing(id)的包装器”。因此,从本质上讲,返回的方法实际上只是method_missing,第一个参数已经被指定为您最初试图获取的方法的id。
我们可以通过验证method_missing的正确率与我们得到的相同来确认我们的怀疑:
A.new.method(:method_missing).arity #=> -1顺便说一句,-1的多重性意味着该方法可以接受无限数量的参数。
至于是否可以让它返回被调用的…方法的“真实”性值不,你不能。首先,Ruby不会假设你的method_missing中发生了什么,甚至不知道它只是简单地委托给其他一些方法。
发布于 2012-12-10 01:58:18
负数表示有最后一个带*前缀的参数。如果有一个必选参数后跟一个*-前缀(即一个必选参数和一个可选的额外量),则该参数将表示为-2,所以-n-1,其中n是所需参数的数量。
- n -1被称为n的1的补码,ruby甚至有一个运算符来获取所需参数的数量,即~运算符。
p ~A.new.method(:foo).arity #=> 0https://stackoverflow.com/questions/13789849
复制相似问题