Spec-Zone.ru › Ruby 2.6

класс Method

Родитель:
Объект

Method объекты создаются Object#method, и связаны с определенным объектом (а не только с классом). Они могут быть использованы для вызова метода внутри объекта, а также в качестве блока, связанного с итератором. Они также могут быть отвязаны от одного объекта (создавая UnboundMethod) и привязаны к другому.

class Thing
  def square(n)
    n*n
  end
end
thing = Thing.new
meth  = thing.method(:square)

meth.call(9)                 #=> 81
[ 1, 2, 3 ].collect(&meth)   #=> [1, 4, 9]

[ 1, 2, 3 ].each(&method(:puts)) #=> prints 1, 2, 3

require 'date'
%w[2017-03-01 2017-03-02].collect(&Date.method(:parse))
#=> [#<Date: 2017-03-01 ((2457814j,0s,0n),+0s,2299161j)>, #<Date: 2017-03-02 ((2457815j,0s,0n),+0s,2299161j)>]

Открытые методы экземпляров

meth << g → a_proc Показать исходный код
static VALUE
rb_method_compose_to_left(VALUE self, VALUE g)
{
    VALUE proc = method_to_proc(self);
    return proc_compose_to_left(proc, g);
}

Возвращает процедуру, являющуюся композицией этого метода и заданного g. Возвращаемая процедура принимает переменное число аргументов, вызывает g с ними, а затем вызывает этот метод с результатом.

def f(x)
  x * x
end

f = self.method(:f)
g = proc {|x| x + x }
p (f << g).call(2) #=> 16
meth == other_meth → true или false Показать исходный код
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;
}

Два объекта метода равны, если они связаны с одним и тем же объектом и ссылаются на одно и то же определение метода, а их владельцы — один и тот же класс или модуль.

method === obj → результат_метода Показать исходный код
VALUE
rb_method_call(int argc, const VALUE *argv, VALUE method)
{
    VALUE procval = rb_block_given_p() ? rb_block_proc() : Qnil;
    return rb_method_call_with_block(argc, argv, method, procval);
}

Вызывает метод с obj в качестве параметра, как в call. Это позволяет объекту метода быть целью when в операторе case.

require 'prime'

case 1373
when Prime.method(:prime?)
  # ...
end
meth >> g → a_proc Показать исходный код
static VALUE
rb_method_compose_to_right(VALUE self, VALUE g)
{
    VALUE proc = method_to_proc(self);
    return proc_compose_to_right(proc, g);
}

Возвращает процедуру, являющуюся композицией этого метода и заданного g. Возвращаемая процедура принимает переменное число аргументов, вызывает g с ними, а затем вызывает этот метод с результатом.

def f(x)
  x * x
end

f = self.method(:f)
g = proc {|x| x + x }
p (f >> g).call(2) #=> 8
meth[args, ...] → obj Показать исходный код
VALUE
rb_method_call(int argc, const VALUE *argv, VALUE method)
{
    VALUE procval = rb_block_given_p() ? rb_block_proc() : Qnil;
    return rb_method_call_with_block(argc, argv, method, procval);
}

Вызывает meth со специфицированными аргументами, возвращая значение, возвращённое методом.

m = 12.method("+")
m.call(3)    #=> 15
m.call(20)   #=> 32
arity → целое число Показать исходный код
static VALUE
method_arity_m(VALUE method)
{
    int n = method_arity(method);
    return INT2FIX(n);
}

Возвращает указание на количество аргументов, принимаемых методом. Возвращает неотрицательное целое число для методов, принимающих фиксированное количество аргументов. Для методов 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
  def seven(a, b, x:0); end
  def eight(x:, y:); end
  def nine(x:, y:, **z); end
  def ten(*a, x:, y:); 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
c.method(:seven).arity   #=> -3
c.method(:eight).arity   #=> 1
c.method(:nine).arity    #=> 1
c.method(:ten).arity     #=> -2

"cat".method(:size).arity      #=> 0
"cat".method(:replace).arity   #=> 1
"cat".method(:squeeze).arity   #=> -1
"cat".method(:count).arity     #=> -1
call(args, ...) → obj Показать исходный код
VALUE
rb_method_call(int argc, const VALUE *argv, VALUE method)
{
    VALUE procval = rb_block_given_p() ? rb_block_proc() : Qnil;
    return rb_method_call_with_block(argc, argv, method, procval);
}

Вызывает meth со специфицированными аргументами, возвращая значение, возвращённое методом.

m = 12.method("+")
m.call(3)    #=> 15
m.call(20)   #=> 32
clone → новый_метод Показать исходный код
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;
}

Возвращает клонированный метод.

class A
  def foo
    return "bar"
  end
end

m = A.new.method(:foo)
m.call # => "bar"
n = m.clone.call # => "bar"
curry → proc Показать исходный код
curry(arity) → proc
static VALUE
rb_method_curry(int argc, const VALUE *argv, VALUE self)
{
    VALUE proc = method_to_proc(self);
    return proc_curry(argc, argv, proc);
}

Возвращает процедуру curried на основе метода. Когда процедура вызывается с количеством аргументов, меньшим чем arity метода, возвращается другая процедура curried. Только когда предоставлено достаточно аргументов для удовлетворения сигнатуры метода, метод фактически вызывается.

Необязательный аргумент arity следует указывать при currying методов с переменным числом аргументов, чтобы определить, сколько аргументов необходимо перед вызовом метода.

def foo(a,b,c)
  [a, b, c]
end

proc  = self.method(:foo).curry
proc2 = proc.call(1, 2)          #=> #<Proc>
proc2.call(3)                    #=> [1,2,3]

def vararg(*args)
  args
end

proc = self.method(:vararg).curry(4)
proc2 = proc.call(:x)      #=> #<Proc>
proc3 = proc2.call(:y, :z) #=> #<Proc>
proc3.call(:a)             #=> [:x, :y, :z, :a]
eql?(other_meth) → true или false Показать исходный код
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 → целое число Показать исходный код
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 ST2FIX(hash);
}

Возвращает значение hash, соответствующее объекту метода.

См. также Object#hash.

inspect → строка Показать исходный код
static VALUE
method_inspect(VALUE method)
{
    struct METHOD *data;
    VALUE str;
    const char *sharp = "#";
    VALUE mklass;
    VALUE defined_class;

    TypedData_Get_Struct(method, struct METHOD, &method_data_type, data);
    str = rb_sprintf("#<% "PRIsVALUE": ", rb_obj_class(method));
    OBJ_INFECT_RAW(str, method);

    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_inspect(mklass));
        if (defined_class != mklass) {
            rb_str_catf(str, "(% "PRIsVALUE")", defined_class);
        }
    }
    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;
}

Возвращает удобочитаемое описание основного метода.

"cat".method(:count).inspect   #=> "#<Method: String#count>"
(1..3).method(:map).inspect    #=> "#<Method: Range(Enumerable)#map>"

В последнем случае описание метода включает «владелец» исходного метода (Enumerable модуль, который включён в Range).

name → символ Показать исходный код
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 → символ Показать исходный код
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);
}

Возвращает исходное имя метода.

class C
  def foo; end
  alias bar foo
end
C.instance_method(:bar).original_name # => :foo
owner → класс_или_модуль Показать исходный код
static VALUE
method_owner(VALUE obj)
{
    struct METHOD *data;
    TypedData_Get_Struct(obj, struct METHOD, &method_data_type, data);
    return data->me->owner;
}

Возвращает класс или модуль, который определяет метод. См. также receiver.

(1..3).method(:map).owner #=> Enumerable
parameters → массив Показать исходный код
static VALUE
rb_method_parameters(VALUE method)
{
    const rb_iseq_t *iseq = rb_method_iseq(method);
    if (!iseq) {
        return rb_unnamed_parameters(method_arity(method));
    }
    return rb_iseq_parameters(iseq, 0);
}

Возвращает информацию о параметрах этого метода.

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]]
receiver → объект Показать исходный код
static VALUE
method_receiver(VALUE obj)
{
    struct METHOD *data;

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

Возвращает связанный объект-приёмник объекта метода.

(1..3).method(:map).receiver # => 1..3
source_location → [Строка, Целое число] Показать исходный код
VALUE
rb_method_location(VALUE method)
{
    return method_def_location(rb_method_def(method));
}

Возвращает имя файла исходного кода Ruby и номер строки, содержащие этот метод, или nil, если этот метод не был определён в Ruby (т.е. нативный).

super_method → метод Показать исходный код
static VALUE
method_super_method(VALUE method)
{
    const struct METHOD *data;
    VALUE super_class, iclass;
    ID mid;
    const rb_method_entry_t *me;

    TypedData_Get_Struct(method, struct METHOD, &method_data_type, data);
    iclass = data->iclass;
    if (!iclass) return Qnil;
    super_class = RCLASS_SUPER(RCLASS_ORIGIN(iclass));
    mid = data->me->called_id;
    if (!super_class) return Qnil;
    me = (rb_method_entry_t *)rb_callable_method_entry_without_refinements(super_class, mid, &iclass);
    if (!me) return Qnil;
    return mnew_internal(me, me->owner, iclass, data->recv, mid, rb_obj_class(method), FALSE, FALSE);
}

Возвращает Method суперкласса, который был бы вызван при использовании super, или nil, если в суперклассе такого метода нет.

to_proc → proc Показать исходный код
static VALUE
method_to_proc(VALUE method)
{
    VALUE procval;
    rb_proc_t *proc;

    /*
     * class Method
     *   def to_proc
     *     lambda{|*args|
     *       self.call(*args)
     *     }
     *   end
     * end
     */
    procval = rb_iterate(mlambda, 0, bmcall, method);
    GetProcPtr(procval, proc);
    proc->is_from_method = 1;
    return procval;
}

Возвращает объект Proc , соответствующий этому методу.

to_s → строка Показать исходный код
static VALUE
method_inspect(VALUE method)
{
    struct METHOD *data;
    VALUE str;
    const char *sharp = "#";
    VALUE mklass;
    VALUE defined_class;

    TypedData_Get_Struct(method, struct METHOD, &method_data_type, data);
    str = rb_sprintf("#<% "PRIsVALUE": ", rb_obj_class(method));
    OBJ_INFECT_RAW(str, method);

    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_inspect(mklass));
        if (defined_class != mklass) {
            rb_str_catf(str, "(% "PRIsVALUE")", defined_class);
        }
    }
    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;
}

Возвращает удобочитаемое описание основного метода.

"cat".method(:count).inspect   #=> "#<Method: String#count>"
(1..3).method(:map).inspect    #=> "#<Method: Range(Enumerable)#map>"

В последнем случае описание метода включает «владелец» исходного метода (Enumerable модуль, который включён в Range).

unbind → несвязанный_метод Показать исходный код
static VALUE
method_unbind(VALUE obj)
{
    VALUE method;
    struct METHOD *orig, *data;

    TypedData_Get_Struct(obj, struct METHOD, &method_data_type, orig);
    method = TypedData_Make_Struct(rb_cUnboundMethod, struct METHOD,
                                   &method_data_type, data);
    RB_OBJ_WRITE(method, &data->recv, Qundef);
    RB_OBJ_WRITE(method, &data->klass, orig->klass);
    RB_OBJ_WRITE(method, &data->me, rb_method_entry_clone(orig->me));
    OBJ_INFECT(method, obj);

    return method;
}

Отсоединяет meth от текущего объекта-приёмника. Полученный UnboundMethod может впоследствии быть связан с новым объектом того же класса (см. UnboundMethod).

Ruby Core © 1993–2017 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API