Ruby 2.4参考手册
UnboundMethod
UnboundMethod
Parent:Object
Ruby支持两种形式的客体化方法。Class Method
用于表示与特定对象关联的方法:这些方法对象绑定到该对象。可以使用创建对象的绑定方法对象Object#method
。
Ruby还支持未绑定的方法; 方法不与特定对象关联的对象。这些可以通过调用Module#instance_method
或通过调用unbind
绑定的方法对象来创建。这两者的结果都是一个UnboundMethod
对象。
未绑定的方法只能在绑定到对象后才能调用。该对象必须是一种kind?该方法的原始类。
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
未绑定的方法是该方法在客体化时的引用:对基础类的后续更改不会影响未绑定的方法。
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
公共实例方法
meth == other_meth → true or false Show source
如果两个方法对象绑定到同一个对象并引用相同的方法定义,并且它们的所有者是相同的类或模块,则它们是相等的。
static VALUE
method_eq(VALUE method, VALUE other)
{
struct METHOD *m1, *m2;
VALUE klass1, klass2;
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);
klass1 = method_entry_defined_class(m1->me);
klass2 = method_entry_defined_class(m2->me);
if (!rb_method_entry_eq(m1->me, m2->me) ||
klass1 != klass2 ||
m1->klass != m2->klass ||
m1->recv != m2->recv) {
return Qfalse;
}
return Qtrue;
}
arity → integer Show source
返回一个方法接受的参数个数的指示。返回具有固定数量参数的方法的非负整数。对于采用可变数量参数的Ruby方法,返回-n-1,其中n是所需参数的数量。对于用C编写的方法,如果调用需要可变数量的参数,则返回-1。
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
static VALUE
method_arity_m(VALUE method)
{
int n = method_arity(method);
return INT2FIX(n);
}
bind(obj) → method Show source
将umeth绑定到obj。如果Klass
是从中获得了umeth的阶级,那么obj.kind_of?(Klass)
必须是真实的。
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
static VALUE
umethod_bind(VALUE method, VALUE recv)
{
struct METHOD *data, *bound;
VALUE methclass, klass;
TypedData_Get_Struct(method, struct METHOD, &method_data_type, data);
methclass = data->me->owner;
if (!RB_TYPE_P(methclass, T_MODULE) &&
methclass != CLASS_OF(recv) && !rb_obj_is_kind_of(recv, methclass)) {
if (FL_TEST(methclass, 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 % "PRIsVALUE,
rb_class_name(methclass));
}
}
klass = CLASS_OF(recv);
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, data->klass);
RB_OBJ_WRITE(method, &bound->me, rb_method_entry_clone(data->me));
if (RB_TYPE_P(bound->me->owner, T_MODULE)) {
VALUE ic = rb_class_search_ancestor(klass, bound->me->owner);
if (ic) {
klass = ic;
}
else {
klass = rb_include_class_new(methclass, klass);
}
RB_OBJ_WRITE(method, &bound->me, rb_method_entry_complement_defined_class(bound->me, bound->me->called_id, klass));
}
return method;
}
clone → new_method Show source
返回此方法的克隆。
class A
def foo
return "bar"
end
end
m = A.new.method(:foo)
m.call # => "bar"
n = m.clone.call # => "bar"
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);
RB_OBJ_WRITE(clone, &data->recv, orig->recv);
RB_OBJ_WRITE(clone, &data->klass, orig->klass);
RB_OBJ_WRITE(clone, &data->me, rb_method_entry_clone(orig->me));
return clone;
}
eql?(other_meth) → true or false Show source
如果两个方法对象绑定到同一个对象并引用相同的方法定义,并且它们的所有者是相同的类或模块,则它们是相等的。
static VALUE
method_eq(VALUE method, VALUE other)
{
struct METHOD *m1, *m2;
VALUE klass1, klass2;
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);
klass1 = method_entry_defined_class(m1->me);
klass2 = method_entry_defined_class(m2->me);
if (!rb_method_entry_eq(m1->me, m2->me) ||
klass1 != klass2 ||
m1->klass != m2->klass ||
m1->recv != m2->recv) {
return Qfalse;
}
return Qtrue;
}
hash → integer Show source
返回与方法对象相对应的哈希值。
另请参阅 Object#hash。
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->recv);
hash = rb_hash_method_entry(hash, m->me);
hash = rb_hash_end(hash);
return INT2FIX(hash);
}
inspect → string Show source
返回基础方法的名称。
"cat".method(:count).inspect #=> "#<Method: String#count>"
static VALUE
method_inspect(VALUE method)
{
struct METHOD *data;
VALUE str;
const char *s;
const char *sharp = "#";
VALUE mklass;
VALUE defined_class;
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, ": ");
mklass = data->klass;
if (data->me->def->type == VM_METHOD_TYPE_ALIAS) {
defined_class = data->me->def->body.alias.original_me->owner;
}
else {
defined_class = method_entry_defined_class(data->me);
}
if (RB_TYPE_P(defined_class, T_ICLASS)) {
defined_class = RBASIC_CLASS(defined_class);
}
if (FL_TEST(mklass, FL_SINGLETON)) {
VALUE v = rb_ivar_get(mklass, attached);
if (data->recv == Qundef) {
rb_str_buf_append(str, rb_inspect(mklass));
}
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_append(str, rb_class_name(mklass));
if (defined_class != mklass) {
rb_str_buf_cat2(str, "(");
rb_str_buf_append(str, rb_class_name(defined_class));
rb_str_buf_cat2(str, ")");
}
}
rb_str_buf_cat2(str, sharp);
rb_str_append(str, rb_id2str(data->me->called_id));
if (data->me->called_id != data->me->def->original_id) {
rb_str_catf(str, "(%"PRIsVALUE")",
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;
}
name → symbol Show source
返回方法的名称。
static VALUE
method_name(VALUE obj)
{
struct METHOD *data;
TypedData_Get_Struct(obj, struct METHOD, &method_data_type, data);
return ID2SYM(data->me->called_id);
}
original_name → symbol Show source
返回方法的原始名称。
static VALUE
method_original_name(VALUE obj)
{
struct METHOD *data;
TypedData_Get_Struct(obj, struct METHOD, &method_data_type, data);
return ID2SYM(data->me->def->original_id);
}
owner → class_or_module Show source
返回定义该方法的类或模块。
static VALUE
method_owner(VALUE obj)
{
struct METHOD *data;
TypedData_Get_Struct(obj, struct METHOD, &method_data_type, data);
return data->me->owner;
}
parameters → array Show source
返回此方法的参数信息。
def foo(bar); end
method(:foo).parameters #=> [[:req, :bar]]
def foo(bar, baz, bat, &blk); end
method(:foo).parameters #=> [[:req, :bar], [:req, :baz], [:req, :bat], [:block, :blk]]
def foo(bar, *args); end
method(:foo).parameters #=> [[:req, :bar], [:rest, :args]]
def foo(bar, baz, *args, &blk); end
method(:foo).parameters #=> [[:req, :bar], [:req, :baz], [:rest, :args], [:block, :blk]]
static VALUE
rb_method_parameters(VALUE method)
{
const rb_iseq_t *iseq = rb_method_iseq(method);
if (!iseq) {
return unnamed_parameters(method_arity(method));
}
return rb_iseq_parameters(iseq, 0);
}
source_location → String, Integer()
返回包含此方法的Ruby源文件名和行号,如果此方法未在Ruby中定义(即本机),则返回nil。
VALUE
rb_method_location(VALUE method)
{
return method_def_location(method_def(method));
}
super_method → method Show source
返回当使用super时会调用的超类的方法,或者如果超类没有方法,则返回nil。
static VALUE
method_super_method(VALUE method)
{
const struct METHOD *data;
VALUE super_class;
const rb_method_entry_t *me;
TypedData_Get_Struct(method, struct METHOD, &method_data_type, data);
super_class = RCLASS_SUPER(method_entry_defined_class(data->me));
if (!super_class) return Qnil;
me = (rb_method_entry_t *)rb_callable_method_entry_without_refinements(super_class, data->me->called_id);
if (!me) return Qnil;
return mnew_internal(me, super_class, data->recv, data->me->called_id, rb_obj_class(method), FALSE, FALSE);
}
to_s → string Show source
返回基础方法的名称。
"cat".method(:count).inspect #=> "#<Method: String#count>"
static VALUE
method_inspect(VALUE method)
{
struct METHOD *data;
VALUE str;
const char *s;
const char *sharp = "#";
VALUE mklass;
VALUE defined_class;
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, ": ");
mklass = data->klass;
if (data->me->def->type == VM_METHOD_TYPE_ALIAS) {
defined_class = data->me->def->body.alias.original_me->owner;
}
else {
defined_class = method_entry_defined_class(data->me);
}
if (RB_TYPE_P(defined_class, T_ICLASS)) {
defined_class = RBASIC_CLASS(defined_class);
}
if (FL_TEST(mklass, FL_SINGLETON)) {
VALUE v = rb_ivar_get(mklass, attached);
if (data->recv == Qundef) {
rb_str_buf_append(str, rb_inspect(mklass));
}
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_append(str, rb_class_name(mklass));
if (defined_class != mklass) {
rb_str_buf_cat2(str, "(");
rb_str_buf_append(str, rb_class_name(defined_class));
rb_str_buf_cat2(str, ")");
}
}
rb_str_buf_cat2(str, sharp);
rb_str_append(str, rb_id2str(data->me->called_id));
if (data->me->called_id != data->me->def->original_id) {
rb_str_catf(str, "(%"PRIsVALUE")",
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;
}
UnboundMethod |
---|
Ruby 是一种面向对象、命令式、函数式、动态的通用编程语言,是世界上最优美而巧妙的语言。
主页 | https://www.ruby-lang.org/ |
源码 | https://github.com/ruby/ruby |
版本 | 2.4 |
发布版本 | 2.4.1 |