123456789_123456789_123456789_123456789_123456789_

Class: UnboundMethod

Relationships & Source Files
Inherits: Object
Defined in: proc.c,
proc.c

Overview

Ruby supports two forms of objectified methods. ::Class Method is used to represent methods that are associated with a particular object: these method objects are bound to that object. Bound method objects for an object can be created using Object#method.

Ruby also supports unbound methods; methods objects that are not associated with a particular object. These can be created either by calling Module#instance_method or by calling #unbind on a bound method object. The result of both of these is an UnboundMethod object.

Unbound methods can only be called after they are bound to an object. That object must be a kind_of? the method’s original class.

class Square
  def area
    @side * @side
  end
  def initialize(side)
    @side = side
  end
end

area_un = Square.instance_method(:area)

s = Square.new(12)
area = area_un.bind(s)
area.call   #=> 144

Unbound methods are a reference to the method at the time it was objectified: subsequent changes to the underlying class will not affect the unbound method.

class Test
  def test
    :original
  end
end
um = Test.instance_method(:test)
class Test
  def test
    :modified
  end
end
t = Test.new
t.test            #=> :modified
um.bind(t).call   #=> :original

Instance Attribute Summary

Instance Method Summary

Instance Attribute Details

#private?Boolean (readonly)

Alias for Method#private?.

#protected?Boolean (readonly)

Alias for Method#protected?.

#public?Boolean (readonly)

Alias for Method#public?.

Instance Method Details

#==(other_meth) ⇒ Boolean Also known as: #eql?

Alias for Method#==.

#arityInteger

Alias for Method#arity.

#bind(obj) ⇒ method

Bind umeth to obj. If Klass was the class from which umeth was obtained, obj.kind_of?(Klass) must be true.

class A
  def test
    puts "In test, class = #{self.class}"
  end
end
class B < A
end
class C < B
end

um = B.instance_method(:test)
bm = um.bind(C.new)
bm.call
bm = um.bind(B.new)
bm.call
bm = um.bind(A.new)
bm.call

produces:

In test, class = C
In test, class = B
prog.rb:16:in `bind': bind argument must be an instance of B (TypeError)
 from prog.rb:16
[ GitHub ]

  
# File 'proc.c', line 2597

static VALUE
umethod_bind(VALUE method, VALUE recv)
{
    VALUE methclass, klass, iclass;
    const rb_method_entry_t *me;
    const struct METHOD *data;
    TypedData_Get_Struct(method, struct METHOD, &method_data_type, data);
    convert_umethod_to_method_components(data, recv, &methclass, &klass, &iclass, &me);

    struct METHOD *bound;
    method = TypedData_Make_Struct(rb_cMethod, struct METHOD, &method_data_type, bound);
    RB_OBJ_WRITE(method, &bound->recv, recv);
    RB_OBJ_WRITE(method, &bound->klass, klass);
    RB_OBJ_WRITE(method, &bound->iclass, iclass);
    RB_OBJ_WRITE(method, &bound->owner, methclass);
    RB_OBJ_WRITE(method, &bound->me, me);

    return method;
}

#bind_call(recv, args, ...) ⇒ Object

Bind umeth to recv and then invokes the method with the specified arguments. This is semantically equivalent to umeth.bind(recv).call(args, ...).

[ GitHub ]

  
# File 'proc.c', line 2625

static VALUE
umethod_bind_call(int argc, VALUE *argv, VALUE method)
{
    rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
    VALUE recv = argv[0];
    argc--;
    argv++;

    VALUE passed_procval = rb_block_given_p() ? rb_block_proc() : Qnil;
    rb_execution_context_t *ec = GET_EC();

    const struct METHOD *data;
    TypedData_Get_Struct(method, struct METHOD, &method_data_type, data);

    const rb_callable_method_entry_t *cme = rb_callable_method_entry(CLASS_OF(recv), data->me->called_id);
    if (data->me == (const rb_method_entry_t *)cme) {
        vm_passed_block_handler_set(ec, proc_to_block_handler(passed_procval));
        return rb_vm_call_kw(ec, recv, cme->called_id, argc, argv, cme, RB_PASS_CALLED_KEYWORDS);
    }
    else {
        VALUE methclass, klass, iclass;
        const rb_method_entry_t *me;
        convert_umethod_to_method_components(data, recv, &methclass, &klass, &iclass, &me);
        struct METHOD bound = { recv, klass, 0, methclass, me };

        return call_method_data(ec, &bound, argc, argv, passed_procval, RB_PASS_CALLED_KEYWORDS);
    }
}

#cloneMethod

Alias for Method#clone.

#==(other_meth) ⇒ Boolean #eql?(other_meth) ⇒ Boolean

Alias for #==.

#hashInteger

Alias for Method#hash.

#to_sString

Alias for Method#inspect.

#nameSymbol

Alias for Method#name.

#original_nameSymbol

#ownerclass_or_module

Alias for Method#owner.

#parametersArray

Alias for Method#parameters.

#source_locationArray, Integer

#super_methodMethod

Alias for Method#super_method.

#to_s

Alias for Method#inspect.

[ GitHub ]