Class: UnboundMethod
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
-
#private? ⇒ Boolean
readonly
Alias for Method#private?.
-
#protected? ⇒ Boolean
readonly
Alias for Method#protected?.
-
#public? ⇒ Boolean
readonly
Alias for Method#public?.
Instance Method Summary
-
#==(other_meth) ⇒ Boolean
(also: #eql?)
Alias for Method#==.
-
#arity ⇒ Integer
Alias for Method#arity.
-
#bind(obj) ⇒ method
Bind umeth to obj.
-
#bind_call(recv, args, ...) ⇒ Object
Bind umeth to recv and then invokes the method with the specified arguments.
-
#clone ⇒ Method
Alias for Method#clone.
-
#eql?(other_meth) ⇒ Boolean
Alias for #==.
-
#hash ⇒ Integer
Alias for Method#hash.
-
#to_s ⇒ String
Alias for Method#inspect.
-
#name ⇒ Symbol
Alias for Method#name.
-
#original_name ⇒ Symbol
Alias for Method#original_name.
-
#owner ⇒ class_or_module
Alias for Method#owner.
-
#parameters ⇒ Array
Alias for Method#parameters.
-
#source_location ⇒ Array, Integer
Alias for Method#source_location.
-
#super_method ⇒ Method
Alias for Method#super_method.
-
#to_s
Alias for Method#inspect.
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#==.
#arity ⇒ Integer
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
# 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, ...)
.
# 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); } }
#clone ⇒ Method
Alias for Method#clone.
#==(other_meth) ⇒ Boolean
#eql?(other_meth) ⇒ Boolean
Boolean
#eql?(other_meth) ⇒ Boolean
Alias for #==.
#hash ⇒ Integer
Alias for Method#hash.
#to_s ⇒ String
Alias for Method#inspect.
#name ⇒ Symbol
Alias for Method#name.
#original_name ⇒ Symbol
Alias for Method#original_name.
#owner ⇒ class_or_module
Alias for Method#owner.
#parameters ⇒ Array
Alias for Method#parameters.
#source_location ⇒ Array, Integer
Alias for Method#source_location.
#super_method ⇒ Method
Alias for Method#super_method.
#to_s
Alias for Method#inspect.