Class: UnboundMethod

Inherits:
Object show all
Defined in:
proc.c,
proc.c

Overview

********************************************************************

Ruby supports two forms of objectified methods. Class
<code>Method</code> 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
<code>Object#method</code>.

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

Unbound methods can only be called after they are bound to an
object. That object must be 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 Method Summary collapse

Instance Method Details

#==(other_meth) ⇒ Boolean

Two method objects are equal if they are bound to the same object and refer to the same method definition and their owners are the same class or module.

Returns:

  • (Boolean)

1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
# File 'proc.c', line 1061

static VALUE
method_eq(VALUE method, VALUE other)
{
    struct METHOD *m1, *m2;

    if (!rb_obj_is_method(other))
	return Qfalse;
    if (CLASS_OF(method) != CLASS_OF(other))
	return Qfalse;

    Check_TypedStruct(method, &method_data_type);
    m1 = (struct METHOD *)DATA_PTR(method);
    m2 = (struct METHOD *)DATA_PTR(other);

    if (!rb_method_entry_eq(m1->me, m2->me) ||
	m1->rclass != m2->rclass ||
	m1->recv != m2->recv) {
	return Qfalse;
    }

    return Qtrue;
}

#arityFixnum

Returns an indication of the number of arguments accepted by a method. Returns a nonnegative integer for methods that take a fixed number of arguments. For Ruby methods that take a variable number of arguments, returns -n-1, where n is the number of required arguments. For methods written in C, returns -1 if the call takes a variable number of arguments.

class C
  def one;    end
  def two(a); end
  def three(*a);  end
  def four(a, b); end
  def five(a, b, *c);    end
  def six(a, b, *c, &d); end
end
c = C.new
c.method(:one).arity     #=> 0
c.method(:two).arity     #=> 1
c.method(:three).arity   #=> -1
c.method(:four).arity    #=> 2
c.method(:five).arity    #=> -3
c.method(:six).arity     #=> -3

"cat".method(:size).arity      #=> 0
"cat".method(:replace).arity   #=> 1
"cat".method(:squeeze).arity   #=> -1
"cat".method(:count).arity     #=> -1

Returns:


1773
1774
1775
1776
1777
1778
# File 'proc.c', line 1773

static VALUE
method_arity_m(VALUE method)
{
    int n = method_arity(method);
    return INT2FIX(n);
}

#bind(obj) ⇒ Object

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

1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
# File 'proc.c', line 1649

static VALUE
umethod_bind(VALUE method, VALUE recv)
{
    struct METHOD *data, *bound;

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

    if (!RB_TYPE_P(data->rclass, T_MODULE) &&
	data->rclass != CLASS_OF(recv) && !rb_obj_is_kind_of(recv, data->rclass)) {
	if (FL_TEST(data->rclass, FL_SINGLETON)) {
	    rb_raise(rb_eTypeError,
		     "singleton method called for a different object");
	}
	else {
	    rb_raise(rb_eTypeError, "bind argument must be an instance of %s",
		     rb_class2name(data->rclass));
	}
    }

    method = TypedData_Make_Struct(rb_cMethod, struct METHOD, &method_data_type, bound);
    *bound = *data;
    bound->me = ALLOC(rb_method_entry_t);
    *bound->me = *data->me;
    if (bound->me->def) bound->me->def->alias_count++;
    bound->recv = recv;
    bound->rclass = CLASS_OF(recv);
    data->ume = ALLOC(struct unlinked_method_entry_list_entry);

    return method;
}

#cloneObject

Returns a clone of this method.

class A
  def foo
    return "bar"
  end
end

m = A.new.method(:foo)
m.call # => "bar"
n = m.clone.call # => "bar"

1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
# File 'proc.c', line 1493

static VALUE
method_clone(VALUE self)
{
    VALUE clone;
    struct METHOD *orig, *data;

    TypedData_Get_Struct(self, struct METHOD, &method_data_type, orig);
    clone = TypedData_Make_Struct(CLASS_OF(self), struct METHOD, &method_data_type, data);
    CLONESETUP(clone, self);
    *data = *orig;
    data->me = ALLOC(rb_method_entry_t);
    *data->me = *orig->me;
    if (data->me->def) data->me->def->alias_count++;
    data->ume = ALLOC(struct unlinked_method_entry_list_entry);

    return clone;
}

#==(other_meth) ⇒ Boolean

Two method objects are equal if they are bound to the same object and refer to the same method definition and their owners are the same class or module.

Returns:

  • (Boolean)

Returns:

  • (Boolean)

1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
# File 'proc.c', line 1061

static VALUE
method_eq(VALUE method, VALUE other)
{
    struct METHOD *m1, *m2;

    if (!rb_obj_is_method(other))
	return Qfalse;
    if (CLASS_OF(method) != CLASS_OF(other))
	return Qfalse;

    Check_TypedStruct(method, &method_data_type);
    m1 = (struct METHOD *)DATA_PTR(method);
    m2 = (struct METHOD *)DATA_PTR(other);

    if (!rb_method_entry_eq(m1->me, m2->me) ||
	m1->rclass != m2->rclass ||
	m1->recv != m2->recv) {
	return Qfalse;
    }

    return Qtrue;
}

#hashInteger

Returns a hash value corresponding to the method object.

Returns:


1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
# File 'proc.c', line 1091

static VALUE
method_hash(VALUE method)
{
    struct METHOD *m;
    st_index_t hash;

    TypedData_Get_Struct(method, struct METHOD, &method_data_type, m);
    hash = rb_hash_start((st_index_t)m->rclass);
    hash = rb_hash_uint(hash, (st_index_t)m->recv);
    hash = rb_hash_method_entry(hash, m->me);
    hash = rb_hash_end(hash);

    return INT2FIX(hash);
}

#to_sString #inspectString

Returns the name of the underlying method.

"cat".method(:count).inspect   #=> "#<Method: String#count>"

Overloads:


1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
# File 'proc.c', line 1928

static VALUE
method_inspect(VALUE method)
{
    struct METHOD *data;
    VALUE str;
    const char *s;
    const char *sharp = "#";

    TypedData_Get_Struct(method, struct METHOD, &method_data_type, data);
    str = rb_str_buf_new2("#<");
    s = rb_obj_classname(method);
    rb_str_buf_cat2(str, s);
    rb_str_buf_cat2(str, ": ");

    if (FL_TEST(data->me->klass, FL_SINGLETON)) {
	VALUE v = rb_ivar_get(data->me->klass, attached);

	if (data->recv == Qundef) {
	    rb_str_buf_append(str, rb_inspect(data->me->klass));
	}
	else if (data->recv == v) {
	    rb_str_buf_append(str, rb_inspect(v));
	    sharp = ".";
	}
	else {
	    rb_str_buf_append(str, rb_inspect(data->recv));
	    rb_str_buf_cat2(str, "(");
	    rb_str_buf_append(str, rb_inspect(v));
	    rb_str_buf_cat2(str, ")");
	    sharp = ".";
	}
    }
    else {
	rb_str_buf_cat2(str, rb_class2name(data->rclass));
	if (data->rclass != data->me->klass) {
	    rb_str_buf_cat2(str, "(");
	    rb_str_buf_cat2(str, rb_class2name(data->me->klass));
	    rb_str_buf_cat2(str, ")");
	}
    }
    rb_str_buf_cat2(str, sharp);
    rb_str_append(str, rb_id2str(data->me->def->original_id));
    if (data->me->def->type == VM_METHOD_TYPE_NOTIMPLEMENTED) {
        rb_str_buf_cat2(str, " (not-implemented)");
    }
    rb_str_buf_cat2(str, ">");

    return str;
}

#nameObject

Returns the name of the method.


1160
1161
1162
1163
1164
1165
1166
1167
# File 'proc.c', line 1160

static VALUE
method_name(VALUE obj)
{
    struct METHOD *data;

    TypedData_Get_Struct(obj, struct METHOD, &method_data_type, data);
    return ID2SYM(data->id);
}

#ownerObject

Returns the class or module that defines the method.


1176
1177
1178
1179
1180
1181
1182
1183
# File 'proc.c', line 1176

static VALUE
method_owner(VALUE obj)
{
    struct METHOD *data;

    TypedData_Get_Struct(obj, struct METHOD, &method_data_type, data);
    return data->me->klass;
}

#parametersArray

Returns the parameter information of this method.

Returns:


1908
1909
1910
1911
1912
1913
1914
1915
1916
# File 'proc.c', line 1908

static VALUE
rb_method_parameters(VALUE method)
{
    rb_iseq_t *iseq = rb_method_get_iseq(method);
    if (!iseq) {
	return unnamed_parameters(method_arity(method));
    }
    return rb_iseq_parameters(iseq, 0);
}

#source_locationArray, Fixnum

Returns the Ruby source filename and line number containing this method or nil if this method was not defined in Ruby (i.e. native)

Returns ].

Returns:


1894
1895
1896
1897
1898
1899
# File 'proc.c', line 1894

VALUE
rb_method_location(VALUE method)
{
    rb_method_definition_t *def = method_get_def(method);
    return method_def_location(def);
}

#to_sString #inspectString

Returns the name of the underlying method.

"cat".method(:count).inspect   #=> "#<Method: String#count>"

Overloads:


1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
# File 'proc.c', line 1928

static VALUE
method_inspect(VALUE method)
{
    struct METHOD *data;
    VALUE str;
    const char *s;
    const char *sharp = "#";

    TypedData_Get_Struct(method, struct METHOD, &method_data_type, data);
    str = rb_str_buf_new2("#<");
    s = rb_obj_classname(method);
    rb_str_buf_cat2(str, s);
    rb_str_buf_cat2(str, ": ");

    if (FL_TEST(data->me->klass, FL_SINGLETON)) {
	VALUE v = rb_ivar_get(data->me->klass, attached);

	if (data->recv == Qundef) {
	    rb_str_buf_append(str, rb_inspect(data->me->klass));
	}
	else if (data->recv == v) {
	    rb_str_buf_append(str, rb_inspect(v));
	    sharp = ".";
	}
	else {
	    rb_str_buf_append(str, rb_inspect(data->recv));
	    rb_str_buf_cat2(str, "(");
	    rb_str_buf_append(str, rb_inspect(v));
	    rb_str_buf_cat2(str, ")");
	    sharp = ".";
	}
    }
    else {
	rb_str_buf_cat2(str, rb_class2name(data->rclass));
	if (data->rclass != data->me->klass) {
	    rb_str_buf_cat2(str, "(");
	    rb_str_buf_cat2(str, rb_class2name(data->me->klass));
	    rb_str_buf_cat2(str, ")");
	}
    }
    rb_str_buf_cat2(str, sharp);
    rb_str_append(str, rb_id2str(data->me->def->original_id));
    if (data->me->def->type == VM_METHOD_TYPE_NOTIMPLEMENTED) {
        rb_str_buf_cat2(str, " (not-implemented)");
    }
    rb_str_buf_cat2(str, ">");

    return str;
}