Spec-Zone.ru › Ruby 2.4

класс Модуль

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

Модуль — это набор методов и констант. Методы в модуле могут быть методами экземпляра или методами модуля. Методы экземпляра отображаются как методы в классе, когда модуль включен, методы модуля — нет. И наоборот, методы модуля могут вызываться без создания объекта-оболочки, а методы экземпляра — нет. (См. Module#module_function. )

В последующих описаниях параметр симв относится к символу, который представляет собой либо строку в кавычках, либо Symbol (например, :name).

module Mod
  include Math
  CONST = 1
  def meth
    #  ...
  end
end
Mod.class              #=> Module
Mod.constants          #=> [:CONST, :PI, :E]
Mod.instance_methods   #=> [:meth]

Методы публичного класса

constants → массив Показать исходный код
constants(inherited) → массив
static VALUE
rb_mod_s_constants(int argc, VALUE *argv, VALUE mod)
{
    const rb_cref_t *cref = rb_vm_cref();
    VALUE klass;
    VALUE cbase = 0;
    void *data = 0;

    if (argc > 0 || mod != rb_cModule) {
        return rb_mod_constants(argc, argv, mod);
    }

    while (cref) {
        klass = CREF_CLASS(cref);
        if (!CREF_PUSHED_BY_EVAL(cref) &&
            !NIL_P(klass)) {
            data = rb_mod_const_at(CREF_CLASS(cref), data);
            if (!cbase) {
                cbase = klass;
            }
        }
        cref = CREF_NEXT(cref);
    }

    if (cbase) {
        data = rb_mod_const_of(cbase, data);
    }
    return rb_const_list(data);
}

В первом варианте возвращается массив имён всех констант, доступных в точке вызова. Этот список включает имена всех модулей и классов, определённых в глобальной области.

Module.constants.first(4)
   # => [:ARGF, :ARGV, :ArgumentError, :Array]

Module.constants.include?(:SEEK_SET)   # => false

class IO
  Module.constants.include?(:SEEK_SET) # => true
end

Второй вариант вызывает метод экземпляра constants.

nesting → массив Показать исходный код
static VALUE
rb_mod_nesting(void)
{
    VALUE ary = rb_ary_new();
    const rb_cref_t *cref = rb_vm_cref();

    while (cref && CREF_NEXT(cref)) {
        VALUE klass = CREF_CLASS(cref);
        if (!CREF_PUSHED_BY_EVAL(cref) &&
            !NIL_P(klass)) {
            rb_ary_push(ary, klass);
        }
        cref = CREF_NEXT(cref);
    }
    return ary;
}

Возвращает список Modules вложенных в точке вызова.

module M1
  module M2
    $a = Module.nesting
  end
end
$a           #=> [M1::M2, M1]
$a[0].name   #=> "M1::M2"
new → модуль Показать исходный код
new {|mod| блок } → модуль
static VALUE
rb_mod_initialize(VALUE module)
{
    if (rb_block_given_p()) {
        rb_mod_module_exec(1, &module, module);
    }
    return Qnil;
}

Создаёт новый анонимный модуль. Если задан блок, он передаётся объекту модуля, и блок вычисляется в контексте этого модуля, подобно module_eval.

fred = Module.new do
  def meth1
    "hello"
  end
  def meth2
    "bye"
  end
end
a = "my string"
a.extend(fred)   #=> "my string"
a.meth1          #=> "hello"
a.meth2          #=> "bye"

Присвойте модуль константе (имя, начинающееся с большой буквы), если хотите обращаться с ним как с обычным модулем.

used_modules → массив Показать исходный код
static VALUE
rb_mod_s_used_modules(void)
{
    const rb_cref_t *cref = rb_vm_cref();
    VALUE ary = rb_ary_new();

    while(cref) {
        if(!NIL_P(CREF_REFINEMENTS(cref))) {
            rb_hash_foreach(CREF_REFINEMENTS(cref), used_modules_i, ary);
        }
        cref = CREF_NEXT(cref);
    }

    return rb_funcall(ary, rb_intern("uniq"), 0);
}

Возвращает массив всех модулей, используемых в текущем объёме. Порядок модулей в результирующем массиве не определён.

module A
  refine Object do
  end
end

module B
  refine Object do
  end
end

using A
using B
p Module.used_modules

возвращает:

[B, A]

Методы публичного экземпляра

mod < other → true, false, or nil Показать исходный код
static VALUE
rb_mod_lt(VALUE mod, VALUE arg)
{
    if (mod == arg) return Qfalse;
    return rb_class_inherited_p(mod, arg);
}

Возвращает true, если mod является подклассом other. Возвращает nil если между ними нет отношения. (Рассматривайте отношение в терминах определения класса: «class A < B» подразумевает «A < B».)

mod <= other → true, false, or nil Показать исходный код
VALUE
rb_class_inherited_p(VALUE mod, VALUE arg)
{
    if (mod == arg) return Qtrue;
    if (!CLASS_OR_MODULE_P(arg) && !RB_TYPE_P(arg, T_ICLASS)) {
        rb_raise(rb_eTypeError, "compared with non class/module");
    }
    if (class_search_ancestor(mod, RCLASS_ORIGIN(arg))) {
        return Qtrue;
    }
    /* not mod < arg; check if mod > arg */
    if (class_search_ancestor(arg, mod)) {
        return Qfalse;
    }
    return Qnil;
}

Возвращает true, если mod является подклассом other или равен other. Возвращает nil если между ними нет отношения. (Рассматривайте отношение в терминах определения класса: «class A < B» подразумевает «A < B».)

module <=> other_module → -1, 0, +1, or nil Показать исходный код
static VALUE
rb_mod_cmp(VALUE mod, VALUE arg)
{
    VALUE cmp;

    if (mod == arg) return INT2FIX(0);
    if (!CLASS_OR_MODULE_P(arg)) {
        return Qnil;
    }

    cmp = rb_class_inherited_p(mod, arg);
    if (NIL_P(cmp)) return Qnil;
    if (cmp) {
        return INT2FIX(-1);
    }
    return INT2FIX(1);
}

Сравнение — Возвращает -1, 0, +1 или nil в зависимости от того, module включает other_module, они одинаковы или module включен в other_module.

Возвращает nil если module не имеет отношения к other_module, если other_module не является модулем или если два значения несравнимы.

obj == other → true or false Показать исходный код
equal?(other) → true or false
eql?(other) → true or false
VALUE
rb_obj_equal(VALUE obj1, VALUE obj2)
{
    if (obj1 == obj2) return Qtrue;
    return Qfalse;
}

Равенство — На уровне Object, == возвращает true только если obj и other являются одним и тем же объектом. Как правило, этот метод переопределяется в дочерних классах для предоставления специфичного для класса значения.

В отличие от ==, метод equal? никогда не должен переопределяться подклассами, поскольку он используется для определения идентичности объекта (то есть a.equal?(b) тогда и только тогда, когда a является тем же объектом, что и b):

obj = "a"
other = obj.dup

obj == other      #=> true
obj.equal? other  #=> false
obj.equal? obj    #=> true

Метод eql? возвращает true если obj и other ссылаются на один и тот же ключ хеша. Это используется методом Hash для проверки членов на равенство. Для объектов класса Object, eql? является синонимом ==. Подклассы обычно продолжают эту традицию, присваивая eql? переопределённому методу ==, но есть исключения. Типы Numeric, например, выполняют преобразование типов через ==, но не через eql?, поэтому:

1 == 1.0     #=> true
1.eql? 1.0   #=> false
mod === obj → true or false Показать исходный код
static VALUE
rb_mod_eqq(VALUE mod, VALUE arg)
{
    return rb_obj_is_kind_of(arg, mod);
}

Равенство по типу — Возвращает true если obj является экземпляром mod или экземпляром одного из потомков mod. Ограниченного использования для модулей, но может быть использовано в операторах case для классификации объектов по классу.

mod > other → true, false, or nil Показать исходный код
static VALUE
rb_mod_gt(VALUE mod, VALUE arg)
{
    if (mod == arg) return Qfalse;
    return rb_mod_ge(mod, arg);
}

Возвращает true, если mod является предком other. Возвращает nil если между ними нет отношения. (Рассматривайте отношение в терминах определения класса: «class A < B» подразумевает «B > A».)

mod >= other → true, false, or nil Показать исходный код
static VALUE
rb_mod_ge(VALUE mod, VALUE arg)
{
    if (!CLASS_OR_MODULE_P(arg)) {
        rb_raise(rb_eTypeError, "compared with non class/module");
    }

    return rb_class_inherited_p(arg, mod);
}

Возвращает true, если mod является предком other или оба модуля одинаковы. Возвращает nil если между ними нет отношения. (Рассматривайте отношение в терминах определения класса: «class A < B» подразумевает «B > A».)

ancestors → array Показать исходный код
VALUE
rb_mod_ancestors(VALUE mod)
{
    VALUE p, ary = rb_ary_new();

    for (p = mod; p; p = RCLASS_SUPER(p)) {
	if (BUILTIN_TYPE(p) == T_ICLASS) {
	    rb_ary_push(ary, RBASIC(p)->klass);
	}
	else if (p == RCLASS_ORIGIN(p)) {
	    rb_ary_push(ary, p);
	}
    }
    return ary;
}

Возвращает список модулей, включённых/представленных в mod (включая сам mod).

module Mod
  include Math
  include Comparable
  prepend Enumerable
end

Mod.ancestors        #=> [Enumerable, Mod, Comparable, Math]
Math.ancestors       #=> [Math]
Enumerable.ancestors #=> [Enumerable]
autoload(module, filename) → nil Показать исходный код
static VALUE
rb_mod_autoload(VALUE mod, VALUE sym, VALUE file)
{
    ID id = rb_to_id(sym);

    FilePathValue(file);
    rb_autoload_str(mod, id, file);
    return Qnil;
}

Регистрирует filename для загрузки (используя Kernel::require) в первый раз, когда module (который может быть String или символом) используется в пространстве имен mod.

module A
end
A.autoload(:B, "b")
A::B.doit            # autoloads "b"
autoload?(name) → String or nil Показать исходный код
static VALUE
rb_mod_autoload_p(VALUE mod, VALUE sym)
{
    ID id = rb_check_id(&sym);
    if (!id) {
        return Qnil;
    }
    return rb_autoload_p(mod, id);
}

Возвращает filename для загрузки, если name зарегистрирован как autoload в пространстве имён mod.

module A
end
A.autoload(:B, "b")
A.autoload?(:B)            #=> "b"
class_eval(string [, filename [, lineno]]) → obj Показать исходный код
class_eval {|mod| block } → obj
VALUE
rb_mod_module_eval(int argc, const VALUE *argv, VALUE mod)
{
    return specific_eval(argc, argv, mod, mod);
}

Вычисляет строку или блок в контексте mod, за исключением того, что при использовании блока поиск констант/классовых переменных не затрагивается. Это можно использовать для добавления методов к классу. module_eval возвращает результат вычисления своего аргумента. Необязательные параметры filename и lineno задают текст сообщений об ошибках.

class Thing
end
a = %q{def hello() "Hello there!" end}
Thing.module_eval(a)
puts Thing.new.hello()
Thing.module_eval("invalid code", "dummy", 123)

выводит:

Hello there!
dummy:123:in `module_eval': undefined local variable
    or method `code' for Thing:Class
class_exec(arg...) {|var...| block } → obj Показать исходный код
VALUE
rb_mod_module_exec(int argc, const VALUE *argv, VALUE mod)
{
    return yield_under(mod, mod, argc, argv);
}

Вычисляет заданный блок в контексте класса/модуля. Метод, определённый в блоке, будет принадлежать получателю. Любые аргументы, переданные методу, будут переданы в блок. Это можно использовать, если блок должен иметь доступ к переменным экземпляра.

class Thing
end
Thing.class_exec{
  def hello() "Hello there!" end
}
puts Thing.new.hello()

выводит:

Hello there!
class_variable_defined?(symbol) → true or false Показать исходный код
class_variable_defined?(string) → true or false
static VALUE
rb_mod_cvar_defined(VALUE obj, VALUE iv)
{
    ID id = id_for_var(obj, iv, a, class);

    if (!id) {
        return Qfalse;
    }
    return rb_cvar_defined(obj, id);
}

Возвращает true если заданная классовая переменная определена в obj. Строковые аргументы преобразуются в символы.

class Fred
  @@foo = 99
end
Fred.class_variable_defined?(:@@foo)    #=> true
Fred.class_variable_defined?(:@@bar)    #=> false
class_variable_get(symbol) → obj Показать исходный код
class_variable_get(string) → obj
static VALUE
rb_mod_cvar_get(VALUE obj, VALUE iv)
{
    ID id = id_for_var(obj, iv, a, class);

    if (!id) {
        rb_name_err_raise("uninitialized class variable %1$s in %2$s",
                          obj, iv);
    }
    return rb_cvar_get(obj, id);
}

Возвращает значение заданной классовой переменной (или вызывает исключение NameError). Часть имени переменной «class_variable» должна быть включена для обычных классовых переменных. Строковые аргументы преобразуются в символы.

class Fred
  @@foo = 99
end
Fred.class_variable_get(:@@foo)     #=> 99
class_variable_set(symbol, obj) → obj Показать исходный код
class_variable_set(string, obj) → obj
static VALUE
rb_mod_cvar_set(VALUE obj, VALUE iv, VALUE val)
{
    ID id = id_for_var(obj, iv, a, class);
    if (!id) id = rb_intern_str(iv);
    rb_cvar_set(obj, id, val);
    return val;
}

Устанавливает классовую переменную, названную symbol, в заданный объект. Если имя классовой переменной передано в виде строки, эта строка преобразуется в символ.

class Fred
  @@foo = 99
  def foo
    @@foo
  end
end
Fred.class_variable_set(:@@foo, 101)     #=> 101
Fred.new.foo                             #=> 101
class_variables(inherit=true) → array Показать исходный код
VALUE
rb_mod_class_variables(int argc, const VALUE *argv, VALUE mod)
{
    VALUE inherit;
    st_table *tbl;

    if (argc == 0) {
	inherit = Qtrue;
    }
    else {
	rb_scan_args(argc, argv, "01", &inherit);
    }
    if (RTEST(inherit)) {
	tbl = mod_cvar_of(mod, 0);
    }
    else {
	tbl = mod_cvar_at(mod, 0);
    }
    return cvar_list(tbl);
}

Возвращает массив имён классовых переменных в mod. Это включает имена классовых переменных во всех включённых модулях, если параметр inherit не установлен в false.

class One
  @@var1 = 1
end
class Two < One
  @@var2 = 2
end
One.class_variables          #=> [:@@var1]
Two.class_variables          #=> [:@@var2, :@@var1]
Two.class_variables(false)   #=> [:@@var2]
const_defined?(sym, inherit=true) → true или false Показать исходный код
const_defined?(str, inherit=true) → true или false
static VALUE
rb_mod_const_defined(int argc, VALUE *argv, VALUE mod)
{
    VALUE name, recur;
    rb_encoding *enc;
    const char *pbeg, *p, *path, *pend;
    ID id;

    rb_check_arity(argc, 1, 2);
    name = argv[0];
    recur = (argc == 1) ? Qtrue : argv[1];

    if (SYMBOL_P(name)) {
        if (!rb_is_const_sym(name)) goto wrong_name;
        id = rb_check_id(&name);
        if (!id) return Qfalse;
        return RTEST(recur) ? rb_const_defined(mod, id) : rb_const_defined_at(mod, id);
    }

    path = StringValuePtr(name);
    enc = rb_enc_get(name);

    if (!rb_enc_asciicompat(enc)) {
        rb_raise(rb_eArgError, "invalid class path encoding (non ASCII)");
    }

    pbeg = p = path;
    pend = path + RSTRING_LEN(name);

    if (p >= pend || !*p) {
      wrong_name:
        rb_name_err_raise(wrong_constant_name, mod, name);
    }

    if (p + 2 < pend && p[0] == ':' && p[1] == ':') {
        mod = rb_cObject;
        p += 2;
        pbeg = p;
    }

    while (p < pend) {
        VALUE part;
        long len, beglen;

        while (p < pend && *p != ':') p++;

        if (pbeg == p) goto wrong_name;

        id = rb_check_id_cstr(pbeg, len = p-pbeg, enc);
        beglen = pbeg-path;

        if (p < pend && p[0] == ':') {
            if (p + 2 >= pend || p[1] != ':') goto wrong_name;
            p += 2;
            pbeg = p;
        }

        if (!id) {
            part = rb_str_subseq(name, beglen, len);
            OBJ_FREEZE(part);
            if (!ISUPPER(*pbeg) || !rb_is_const_name(part)) {
                name = part;
                goto wrong_name;
            }
            else {
                return Qfalse;
            }
        }
        if (!rb_is_const_id(id)) {
            name = ID2SYM(id);
            goto wrong_name;
        }
        if (RTEST(recur)) {
            if (!rb_const_defined(mod, id))
                return Qfalse;
            mod = rb_const_get(mod, id);
        }
        else {
            if (!rb_const_defined_at(mod, id))
                return Qfalse;
            mod = rb_const_get_at(mod, id);
        }
        recur = Qfalse;

        if (p < pend && !RB_TYPE_P(mod, T_MODULE) && !RB_TYPE_P(mod, T_CLASS)) {
            rb_raise(rb_eTypeError, "%"PRIsVALUE" does not refer to class/module",
                     QUOTE(name));
        }
    }

    return Qtrue;
}

Указывает, есть ли у mod или его предков константа с заданным именем:

Float.const_defined?(:EPSILON)      #=> true, found in Float itself
Float.const_defined?("String")      #=> true, found in Object (ancestor)
BasicObject.const_defined?(:Hash)   #=> false

Если mod является Module, дополнительно проверяются Object и его предки:

Math.const_defined?(:String)   #=> true, found in Object

В каждом из проверяемых классов или модулей, если константа отсутствует, но есть автозагрузка для неё, true возвращается напрямую без автозагрузки:

module Admin
  autoload :User, 'admin/user'
end
Admin.const_defined?(:User)   #=> true

Если константа не найдена, обратный вызов const_missing не вызывается, и метод возвращает false.

Если inherit равно false, поиск выполняется только среди констант получателя:

IO.const_defined?(:SYNC)          #=> true, found in File::Constants (ancestor)
IO.const_defined?(:SYNC, false)   #=> false, not found in IO itself

В этом случае применяется та же логика автозагрузки.

Если аргумент не является допустимым именем константы, генерируется NameError с сообщением «неверное имя константы name»:

Hash.const_defined? 'foobar'   #=> NameError: wrong constant name foobar
const_get(sym, inherit=true) → obj Показать исходный код
const_get(str, inherit=true) → obj
static VALUE
rb_mod_const_get(int argc, VALUE *argv, VALUE mod)
{
    VALUE name, recur;
    rb_encoding *enc;
    const char *pbeg, *p, *path, *pend;
    ID id;

    rb_check_arity(argc, 1, 2);
    name = argv[0];
    recur = (argc == 1) ? Qtrue : argv[1];

    if (SYMBOL_P(name)) {
        if (!rb_is_const_sym(name)) goto wrong_name;
        id = rb_check_id(&name);
        if (!id) return rb_const_missing(mod, name);
        return RTEST(recur) ? rb_const_get(mod, id) : rb_const_get_at(mod, id);
    }

    path = StringValuePtr(name);
    enc = rb_enc_get(name);

    if (!rb_enc_asciicompat(enc)) {
        rb_raise(rb_eArgError, "invalid class path encoding (non ASCII)");
    }

    pbeg = p = path;
    pend = path + RSTRING_LEN(name);

    if (p >= pend || !*p) {
      wrong_name:
        rb_name_err_raise(wrong_constant_name, mod, name);
    }

    if (p + 2 < pend && p[0] == ':' && p[1] == ':') {
        mod = rb_cObject;
        p += 2;
        pbeg = p;
    }

    while (p < pend) {
        VALUE part;
        long len, beglen;

        while (p < pend && *p != ':') p++;

        if (pbeg == p) goto wrong_name;

        id = rb_check_id_cstr(pbeg, len = p-pbeg, enc);
        beglen = pbeg-path;

        if (p < pend && p[0] == ':') {
            if (p + 2 >= pend || p[1] != ':') goto wrong_name;
            p += 2;
            pbeg = p;
        }

        if (!RB_TYPE_P(mod, T_MODULE) && !RB_TYPE_P(mod, T_CLASS)) {
            rb_raise(rb_eTypeError, "%"PRIsVALUE" does not refer to class/module",
                     QUOTE(name));
        }

        if (!id) {
            part = rb_str_subseq(name, beglen, len);
            OBJ_FREEZE(part);
            if (!ISUPPER(*pbeg) || !rb_is_const_name(part)) {
                name = part;
                goto wrong_name;
            }
            else if (!rb_method_basic_definition_p(CLASS_OF(mod), id_const_missing)) {
                part = rb_str_intern(part);
                mod = rb_const_missing(mod, part);
                continue;
            }
            else {
                rb_mod_const_missing(mod, part);
            }
        }
        if (!rb_is_const_id(id)) {
            name = ID2SYM(id);
            goto wrong_name;
        }
        mod = RTEST(recur) ? rb_const_get(mod, id) : rb_const_get_at(mod, id);
    }

    return mod;
}

Ищет константу с заданным именем в mod. Если inherit установлено, поиск также будет производиться среди предков (и Object если mod является Module).

Если определение константы найдено, возвращается её значение, в противном случае генерируется NameError.

Math.const_get(:PI)   #=> 3.14159265358979

Этот метод будет рекурсивно искать имена констант, если предоставлено имя класса с пространством имён. Например:

module Foo; class Bar; end end
Object.const_get 'Foo::Bar'

Флаг inherit учитывается при каждом поиске. Например:

module Foo
  class Bar
    VAL = 10
  end

  class Baz < Bar; end
end

Object.const_get 'Foo::Baz::VAL'         # => 10
Object.const_get 'Foo::Baz::VAL', false  # => NameError

Если аргумент не является допустимым именем константы, генерируется NameError с предупреждением «неверное имя константы».

Object.const_get 'foobar' #=> NameError: wrong constant name foobar
const_missing(sym) → obj Показать исходный код
VALUE
rb_mod_const_missing(VALUE klass, VALUE name)
{
    rb_vm_pop_cfunc_frame();
    uninitialized_constant(klass, name);

    UNREACHABLE;
}

Вызывается, когда делается ссылка на неопределённую константу в mod. Ему передаётся символ неопределённой константы, и он возвращает значение, которое должно быть использовано для этой константы. Следующий код является примером того же:

def Foo.const_missing(name)
  name # return the constant name as Symbol
end

Foo::UNDEFINED_CONST    #=> :UNDEFINED_CONST: symbol returned

В следующем примере, когда делается ссылка на неопределённую константу, он пытается загрузить файл, имя которого является нижним регистром константы (следовательно, предполагается, что класс Fred находится в файле fred.rb). Если найден, он возвращает загруженный класс. Таким образом, он реализует функцию автозагрузки, аналогичную Kernel#autoload и #autoload.

def Object.const_missing(name)
  @looked_for ||= {}
  str_name = name.to_s
  raise "Class not found: #{name}" if @looked_for[str_name]
  @looked_for[str_name] = 1
  file = str_name.downcase
  require file
  klass = const_get(name)
  return klass if klass
  raise "Class not found: #{name}"
end
const_set(sym, obj) → obj Показать исходный код
const_set(str, obj) → obj
static VALUE
rb_mod_const_set(VALUE mod, VALUE name, VALUE value)
{
    ID id = id_for_setter(mod, name, const, wrong_constant_name);
    if (!id) id = rb_intern_str(name);
    rb_const_set(mod, id, value);

    return value;
}

Устанавливает значение именованной константы в заданный объект, возвращая этот объект. Создаёт новую константу, если константа с заданным именем ранее не существовала.

Math.const_set("HIGH_SCHOOL_PI", 22.0/7.0)   #=> 3.14285714285714
Math::HIGH_SCHOOL_PI - Math::PI              #=> 0.00126448926734968

Если sym или str не являются допустимыми именами константы, генерируется NameError с предупреждением «неверное имя константы».

Object.const_set('foobar', 42) #=> NameError: wrong constant name foobar
constants(inherit=true) → массив Показать исходный код
VALUE
rb_mod_constants(int argc, const VALUE *argv, VALUE mod)
{
    VALUE inherit;

    if (argc == 0) {
	inherit = Qtrue;
    }
    else {
	rb_scan_args(argc, argv, "01", &inherit);
    }

    if (RTEST(inherit)) {
	return rb_const_list(rb_mod_const_of(mod, 0));
    }
    else {
	return rb_local_constants(mod);
    }
}

Возвращает массив имён констант, доступных в mod. Это включает имена констант во всех включённых модулях (пример в начале раздела), если параметр inherit не установлен в false.

Реализация не гарантирует порядок, в котором константы возвращаются.

IO.constants.include?(:SYNC)        #=> true
IO.constants(false).include?(:SYNC) #=> false

См. также Module::const_defined?.

deprecate_constant(symbol, ...) → mod Показать исходный код
VALUE
rb_mod_deprecate_constant(int argc, const VALUE *argv, VALUE obj)
{
    set_const_visibility(obj, argc, argv, CONST_DEPRECATED, CONST_DEPRECATED);
    return obj;
}

Помечает список существующих констант как устаревшие.

freeze → mod Показать исходный код
static VALUE
rb_mod_freeze(VALUE mod)
{
    rb_class_name(mod);
    return rb_obj_freeze(mod);
}

Запрещает дальнейшие изменения в mod.

Этот метод возвращает self.

include(module, ...) → self Показать исходный код
static VALUE
rb_mod_include(int argc, VALUE *argv, VALUE module)
{
    int i;
    ID id_append_features, id_included;

    CONST_ID(id_append_features, "append_features");
    CONST_ID(id_included, "included");

    rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
    for (i = 0; i < argc; i++)
        Check_Type(argv[i], T_MODULE);
    while (argc--) {
        rb_funcall(argv[argc], id_append_features, 1, module);
        rb_funcall(argv[argc], id_included, 1, module);
    }
    return module;
}

Вызывает Module.append_features для каждого параметра в обратном порядке.

include?(module) → true или false Показать исходный код
VALUE
rb_mod_include_p(VALUE mod, VALUE mod2)
{
    VALUE p;

    Check_Type(mod2, T_MODULE);
    for (p = RCLASS_SUPER(mod); p; p = RCLASS_SUPER(p)) {
	if (BUILTIN_TYPE(p) == T_ICLASS) {
	    if (RBASIC(p)->klass == mod2) return Qtrue;
	}
    }
    return Qfalse;
}

Возвращает true если module включён в mod или в одном из предков mod.

module A
end
class B
  include A
end
class C < B
end
B.include?(A)   #=> true
C.include?(A)   #=> true
A.include?(A)   #=> false
included_modules → массив Показать исходный код
VALUE
rb_mod_included_modules(VALUE mod)
{
    VALUE ary = rb_ary_new();
    VALUE p;
    VALUE origin = RCLASS_ORIGIN(mod);

    for (p = RCLASS_SUPER(mod); p; p = RCLASS_SUPER(p)) {
	if (p != origin && BUILTIN_TYPE(p) == T_ICLASS) {
	    VALUE m = RBASIC(p)->klass;
	    if (RB_TYPE_P(m, T_MODULE))
		rb_ary_push(ary, m);
	}
    }
    return ary;
}

Возвращает список модулей, включённых в mod.

module Mixin
end

module Outer
  include Mixin
end

Mixin.included_modules   #=> []
Outer.included_modules   #=> [Mixin]
inspect()
Псевдоним для: to_s
instance_method(symbol) → unbound_method Показать исходный код
static VALUE
rb_mod_instance_method(VALUE mod, VALUE vid)
{
    ID id = rb_check_id(&vid);
    if (!id) {
        rb_method_name_error(mod, vid);
    }
    return mnew(mod, Qundef, id, rb_cUnboundMethod, FALSE);
}

Возвращает UnboundMethod, представляющий указанный метод экземпляра в mod.

class Interpreter
  def do_a() print "there, "; end
  def do_d() print "Hello ";  end
  def do_e() print "!\n";     end
  def do_v() print "Dave";    end
  Dispatcher = {
    "a" => instance_method(:do_a),
    "d" => instance_method(:do_d),
    "e" => instance_method(:do_e),
    "v" => instance_method(:do_v)
  }
  def interpret(string)
    string.each_char {|b| Dispatcher[b].bind(self).call }
  end
end

interpreter = Interpreter.new
interpreter.interpret('dave')

выводит:

Hello there, Dave!
instance_methods(include_super=true) → массив Показать исходный код
VALUE
rb_class_instance_methods(int argc, const VALUE *argv, VALUE mod)
{
    return class_instance_method_list(argc, argv, mod, 0, ins_methods_i);
}

Возвращает массив, содержащий имена публичных и защищённых методов экземпляра в получателе. Для модуля — это публичные и защищённые методы; для класса — методы экземпляра (а не одиночные методы). Если необязательный параметр false, методы предков не включаются.

module A
  def method1()  end
end
class B
  include A
  def method2()  end
end
class C < B
  def method3()  end
end

A.instance_methods(false)                   #=> [:method1]
B.instance_methods(false)                   #=> [:method2]
B.instance_methods(true).include?(:method1) #=> true
C.instance_methods(false)                   #=> [:method3]
C.instance_methods.include?(:method2)       #=> true
method_defined?(symbol) → true или false
method_defined?(string) → true или false
static VALUE
rb_mod_method_defined(VALUE mod, VALUE mid)
{
    ID id = rb_check_id(&mid);
    if (!id || !rb_method_boundp(mod, id, 1)) {
        return Qfalse;
    }
    return Qtrue;

}

Возвращает true если указанный метод определён mod (или его включёнными модулями, и, если mod является классом, его предками). Сопоставляются публичные и защищённые методы. Аргументы типа String преобразуются в символы.

module A
  def method1()  end
  def protected_method1()  end
  protected :protected_method1
end
class B
  def method2()  end
  def private_method2()  end
  private :private_method2
end
class C < B
  include A
  def method3()  end
end

A.method_defined? :method1              #=> true
C.method_defined? "method1"             #=> true
C.method_defined? "method2"             #=> true
C.method_defined? "method3"             #=> true
C.method_defined? "protected_method1"   #=> true
C.method_defined? "method4"             #=> false
C.method_defined? "private_method2"     #=> false
module_eval(string [, filename [, lineno]]) → obj Показать исходный код
module_eval {|mod| блок } → obj
VALUE
rb_mod_module_eval(int argc, const VALUE *argv, VALUE mod)
{
    return specific_eval(argc, argv, mod, mod);
}

Вычисляет строку или блок в контексте mod, за исключением того, что при использовании блока поиск констант/переменных класса не изменяется. Это может быть использовано для добавления методов к классу. module_eval возвращает результат вычисления своего аргумента. Необязательные параметры filename и lineno задают текст сообщений об ошибках.

class Thing
end
a = %q{def hello() "Hello there!" end}
Thing.module_eval(a)
puts Thing.new.hello()
Thing.module_eval("invalid code", "dummy", 123)

выводит:

Hello there!
dummy:123:in `module_eval': undefined local variable
    or method `code' for Thing:Class
module_exec(arg...) {|var...| блок } → obj Показать исходный код
VALUE
rb_mod_module_exec(int argc, const VALUE *argv, VALUE mod)
{
    return yield_under(mod, mod, argc, argv);
}

Вычисляет указанный блок в контексте класса/модуля. Метод, определённый в блоке, будет принадлежать получателю. Любые аргументы, переданные методу, будут переданы блоку. Это может быть использовано, если блоку необходимо получить доступ к переменным экземпляра.

class Thing
end
Thing.class_exec{
  def hello() "Hello there!" end
}
puts Thing.new.hello()

выводит:

Hello there!
name → строка Показать исходный код
VALUE
rb_mod_name(VALUE mod)
{
    int permanent;
    VALUE path = classname(mod, &permanent);

    if (!NIL_P(path)) return rb_str_dup(path);
    return path;
}

Возвращает имя модуля mod. Возвращает nil для анонимных модулей.

prepend(модуль, ...) → self Показать исходный код
static VALUE
rb_mod_prepend(int argc, VALUE *argv, VALUE module)
{
    int i;
    ID id_prepend_features, id_prepended;

    CONST_ID(id_prepend_features, "prepend_features");
    CONST_ID(id_prepended, "prepended");

    rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
    for (i = 0; i < argc; i++)
        Check_Type(argv[i], T_MODULE);
    while (argc--) {
        rb_funcall(argv[argc], id_prepend_features, 1, module);
        rb_funcall(argv[argc], id_prepended, 1, module);
    }
    return module;
}

Вызывает Module.prepend_features для каждого параметра в обратном порядке.

private_class_method(символ, ...) → mod Показать исходный код
private_class_method(строка, ...) → mod
static VALUE
rb_mod_private_method(int argc, VALUE *argv, VALUE obj)
{
    set_method_visibility(rb_singleton_class(obj), argc, argv, METHOD_VISI_PRIVATE);
    return obj;
}

Делает существующие методы класса закрытыми. Часто используется для скрытия конструктора по умолчанию new.

Строковые аргументы преобразуются в символы.

class SimpleSingleton  # Not thread safe
  private_class_method :new
  def SimpleSingleton.create(*args, &block)
    @me = new(*args, &block) if ! @me
    @me
  end
end
private_constant(символ, ...) → mod Показать исходный код
VALUE
rb_mod_private_constant(int argc, const VALUE *argv, VALUE obj)
{
    set_const_visibility(obj, argc, argv, CONST_PRIVATE, CONST_VISIBILITY_MASK);
    return obj;
}

Делает список существующих констант закрытыми.

private_instance_methods(include_super=true) → массив Показать исходный код
VALUE
rb_class_private_instance_methods(int argc, const VALUE *argv, VALUE mod)
{
    return class_instance_method_list(argc, argv, mod, 0, ins_methods_priv_i);
}

Возвращает список закрытых методов экземпляра, определенных в mod. Если необязательный параметр равен false, методы предков не включаются.

module Mod
  def method1()  end
  private :method1
  def method2()  end
end
Mod.instance_methods           #=> [:method2]
Mod.private_instance_methods   #=> [:method1]
private_method_defined?(символ) → true или false Показать исходный код
private_method_defined?(строка) → true или false
static VALUE
rb_mod_private_method_defined(VALUE mod, VALUE mid)
{
    return check_definition(mod, mid, METHOD_VISI_PRIVATE);
}

Возвращает true, если закрытый метод с указанным именем определен в mod (или его включенных модулях, а если mod — класс, то и в его предках). Строковые аргументы преобразуются в символы.

module A
  def method1()  end
end
class B
  private
  def method2()  end
end
class C < B
  include A
  def method3()  end
end

A.method_defined? :method1            #=> true
C.private_method_defined? "method1"   #=> false
C.private_method_defined? "method2"   #=> true
C.method_defined? "method2"           #=> false
protected_instance_methods(include_super=true) → массив Показать исходный код
VALUE
rb_class_protected_instance_methods(int argc, const VALUE *argv, VALUE mod)
{
    return class_instance_method_list(argc, argv, mod, 0, ins_methods_prot_i);
}

Возвращает список защищённых методов экземпляра, определенных в mod. Если необязательный параметр равен false, методы предков не включаются.

protected_method_defined?(символ) → true или false Показать исходный код
protected_method_defined?(строка) → true или false
static VALUE
rb_mod_protected_method_defined(VALUE mod, VALUE mid)
{
    return check_definition(mod, mid, METHOD_VISI_PROTECTED);
}

Возвращает true, если защищённый метод с указанным именем определён в mod (или его включенных модулях, а если mod — класс, то и в его предках). Строковые аргументы преобразуются в символы.

module A
  def method1()  end
end
class B
  protected
  def method2()  end
end
class C < B
  include A
  def method3()  end
end

A.method_defined? :method1              #=> true
C.protected_method_defined? "method1"   #=> false
C.protected_method_defined? "method2"   #=> true
C.method_defined? "method2"             #=> true
psych_yaml_as(url) Показать исходный код
# File ext/psych/lib/psych/core_ext.rb, line 21
def psych_yaml_as url
  return if caller[0].end_with?('rubytypes.rb')
  if $VERBOSE
    warn "#{caller[0]}: yaml_as is deprecated, please use yaml_tag"
  end
  Psych.add_tag(url, self)
end
Также алиас: yaml_as
public_class_method(символ, ...) → mod Показать исходный код
public_class_method(строка, ...) → mod
static VALUE
rb_mod_public_method(int argc, VALUE *argv, VALUE obj)
{
    set_method_visibility(rb_singleton_class(obj), argc, argv, METHOD_VISI_PUBLIC);
    return obj;
}

Делает список существующих методов класса общедоступными.

Строковые аргументы преобразуются в символы.

public_constant(символ, ...) → mod Показать исходный код
VALUE
rb_mod_public_constant(int argc, const VALUE *argv, VALUE obj)
{
    set_const_visibility(obj, argc, argv, CONST_PUBLIC, CONST_VISIBILITY_MASK);
    return obj;
}

Делает список существующих констант общедоступными.

public_instance_method(символ) → unbound_method Показать исходный код
static VALUE
rb_mod_public_instance_method(VALUE mod, VALUE vid)
{
    ID id = rb_check_id(&vid);
    if (!id) {
        rb_method_name_error(mod, vid);
    }
    return mnew(mod, Qundef, id, rb_cUnboundMethod, TRUE);
}

Аналогично instance_method, но ищет только общедоступные методы.

public_instance_methods(include_super=true) → массив Показать исходный код
VALUE
rb_class_public_instance_methods(int argc, const VALUE *argv, VALUE mod)
{
    return class_instance_method_list(argc, argv, mod, 0, ins_methods_pub_i);
}

Возвращает список общедоступных методов экземпляра, определённых в mod. Если необязательный параметр равен false, методы предков не включаются.

public_method_defined?(символ) → true или false Показать исходный код
public_method_defined?(строка) → true или false
static VALUE
rb_mod_public_method_defined(VALUE mod, VALUE mid)
{
    return check_definition(mod, mid, METHOD_VISI_PUBLIC);
}

Возвращает true, если общедоступный метод с указанным именем определен в mod (или его включенных модулях, а если mod — класс, то и в его предках). Строковые аргументы преобразуются в символы.

module A
  def method1()  end
end
class B
  protected
  def method2()  end
end
class C < B
  include A
  def method3()  end
end

A.method_defined? :method1           #=> true
C.public_method_defined? "method1"   #=> true
C.public_method_defined? "method2"   #=> false
C.method_defined? "method2"          #=> true
remove_class_variable(sym) → obj Показать исходный код
VALUE
rb_mod_remove_cvar(VALUE mod, VALUE name)
{
    const ID id = id_for_var_message(mod, name, class, "wrong class variable name %1$s");
    st_data_t val, n = id;

    if (!id) {
      not_defined:
	rb_name_err_raise("class variable %1$s not defined for %2$s",
			  mod, name);
    }
    rb_check_frozen(mod);
    if (RCLASS_IV_TBL(mod) && st_delete(RCLASS_IV_TBL(mod), &n, &val)) {
	return (VALUE)val;
    }
    if (rb_cvar_defined(mod, id)) {
	rb_name_err_raise("cannot remove %1$s for %2$s", mod, ID2SYM(id));
    }
    goto not_defined;
}

Удаляет определение sym, возвращая значение этой константы.

class Dummy
  @@var = 99
  puts @@var
  remove_class_variable(:@@var)
  p(defined? @@var)
end

результат:

99
nil
singleton_class? → true или false Показать исходный код
static VALUE
rb_mod_singleton_p(VALUE klass)
{
    if (RB_TYPE_P(klass, T_CLASS) && FL_TEST(klass, FL_SINGLETON))
        return Qtrue;
    return Qfalse;
}

Возвращает true, если mod — единственный класс, или false, если это обычный класс или модуль.

class C
end
C.singleton_class?                  #=> false
C.singleton_class.singleton_class?  #=> true
to_s → строка Показать исходный код
static VALUE
rb_mod_to_s(VALUE klass)
{
    ID id_defined_at;
    VALUE refined_class, defined_at;

    if (FL_TEST(klass, FL_SINGLETON)) {
        VALUE s = rb_usascii_str_new2("#<Class:");
        VALUE v = rb_ivar_get(klass, id__attached__);

        if (CLASS_OR_MODULE_P(v)) {
            rb_str_append(s, rb_inspect(v));
        }
        else {
            rb_str_append(s, rb_any_to_s(v));
        }
        rb_str_cat2(s, ">");

        return s;
    }
    refined_class = rb_refinement_module_get_refined_class(klass);
    if (!NIL_P(refined_class)) {
        VALUE s = rb_usascii_str_new2("#<refinement:");

        rb_str_concat(s, rb_inspect(refined_class));
        rb_str_cat2(s, "@");
        CONST_ID(id_defined_at, "__defined_at__");
        defined_at = rb_attr_get(klass, id_defined_at);
        rb_str_concat(s, rb_inspect(defined_at));
        rb_str_cat2(s, ">");
        return s;
    }
    return rb_str_dup(rb_class_name(klass));
}

Возвращает строку, представляющую этот модуль или класс. Для базовых классов и модулей это имя. Для единственных классов, мы показываем информацию об объекте, к которому мы прикреплены.

Также алиас: inspect
yaml_as(url)
Псевдоним для: psych_yaml_as

Приватные методы экземпляра

alias_method(new_name, old_name) → self Show source
static VALUE
rb_mod_alias_method(VALUE mod, VALUE newname, VALUE oldname)
{
    ID oldid = rb_check_id(&oldname);
    if (!oldid) {
        rb_print_undef_str(mod, oldname);
    }
    rb_alias(mod, rb_to_id(newname), oldid);
    return mod;
}

Создает new_name — новую копию метода old_name. Это может использоваться для сохранения доступа к методам, которые переопределены.

module Mod
  alias_method :orig_exit, :exit
  def exit(code=0)
    puts "Exiting with code #{code}"
    orig_exit(code)
  end
end
include Mod
exit(99)

результат:

Exiting with code 99
append_features(mod) → mod Show source
static VALUE
rb_mod_append_features(VALUE module, VALUE include)
{
    if (!CLASS_OR_MODULE_P(include)) {
        Check_Type(include, T_CLASS);
    }
    rb_include_module(include, module);

    return module;
}

Когда этот модуль включается в другой, Ruby вызывает append_features в этом модуле, передавая ему принимающий модуль в mod. Реализация по умолчанию в Ruby заключается в добавлении констант, методов и переменных модуля к mod, если этот модуль еще не был добавлен к mod или одному из его предков. См. также Module#include.

attr(*args) Show source
VALUE
rb_mod_attr(int argc, VALUE *argv, VALUE klass)
{
    if (argc == 2 && (argv[1] == Qtrue || argv[1] == Qfalse)) {
        rb_warning("optional boolean argument is obsoleted");
        rb_attr(klass, id_for_attr(klass, argv[0]), 1, RTEST(argv[1]), TRUE);
        return Qnil;
    }
    return rb_mod_attr_reader(argc, argv, klass);
}
attr_accessor(symbol, ...) → nil Show source
attr_accessor(string, ...) → nil
static VALUE
rb_mod_attr_accessor(int argc, VALUE *argv, VALUE klass)
{
    int i;

    for (i=0; i<argc; i++) {
        rb_attr(klass, id_for_attr(klass, argv[i]), TRUE, TRUE, TRUE);
    }
    return Qnil;
}

Определяет именованный атрибут для этого модуля, где имя — это symbol.id2name, создавая переменную экземпляра (@name) и соответствующий метод доступа для ее чтения. Также создает метод, называемый name=, для установки атрибута. Аргументы типа строка преобразуются в символы.

module Mod
  attr_accessor(:one, :two)
end
Mod.instance_methods.sort   #=> [:one, :one=, :two, :two=]
attr_reader(symbol, ...) → nil Show source
attr(symbol, ...) → nil
attr_reader(string, ...) → nil
attr(string, ...) → nil
static VALUE
rb_mod_attr_reader(int argc, VALUE *argv, VALUE klass)
{
    int i;

    for (i=0; i<argc; i++) {
        rb_attr(klass, id_for_attr(klass, argv[i]), TRUE, FALSE, TRUE);
    }
    return Qnil;
}

Создает переменные экземпляра и соответствующие методы, которые возвращают значение каждой переменной экземпляра. Эквивалентно вызову "attr:name" для каждого имени по очереди. Аргументы типа строка преобразуются в символы.

attr_writer(symbol, ...) → nil Show source
attr_writer(string, ...) → nil
static VALUE
rb_mod_attr_writer(int argc, VALUE *argv, VALUE klass)
{
    int i;

    for (i=0; i<argc; i++) {
        rb_attr(klass, id_for_attr(klass, argv[i]), FALSE, TRUE, TRUE);
    }
    return Qnil;
}

Создает метод доступа для присваивания значения атрибуту symbol.id2name. Аргументы типа строка преобразуются в символы.

define_method(symbol, method) → symbol Show source
define_method(symbol) { block } → symbol
static VALUE
rb_mod_define_method(int argc, VALUE *argv, VALUE mod)
{
    ID id;
    VALUE body;
    VALUE name;
    const rb_cref_t *cref = rb_vm_cref_in_context(mod, mod);
    const rb_scope_visibility_t default_scope_visi = {METHOD_VISI_PUBLIC, FALSE};
    const rb_scope_visibility_t *scope_visi = &default_scope_visi;
    int is_method = FALSE;

    if (cref) {
        scope_visi = CREF_SCOPE_VISI(cref);
    }

    rb_check_arity(argc, 1, 2);
    name = argv[0];
    id = rb_check_id(&name);
    if (argc == 1) {
#if PROC_NEW_REQUIRES_BLOCK
        body = rb_block_lambda();
#else
        rb_thread_t *th = GET_THREAD();
        VALUE block_handler = rb_vm_frame_block_handler(th->cfp);
        if (block_handler == VM_BLOCK_HANDLER_NONE) rb_raise(rb_eArgError, proc_without_block);

        switch (vm_block_handler_type(block_handler)) {
          case block_handler_type_proc:
            body = VM_BH_TO_PROC(block_handler);
            break;
          case block_handler_type_symbol:
            body = rb_sym_to_proc(VM_BH_TO_SYMBOL(block_handler));
            break;
          case block_handler_type_iseq:
          case block_handler_type_ifunc:
            body = rb_vm_make_proc_lambda(th, VM_BH_TO_CAPT_BLOCK(block_handler), rb_cProc, TRUE);
        }
#endif
    }
    else {
        body = argv[1];

        if (rb_obj_is_method(body)) {
            is_method = TRUE;
        }
        else if (rb_obj_is_proc(body)) {
            is_method = FALSE;
        }
        else {
            rb_raise(rb_eTypeError,
                     "wrong argument type %s (expected Proc/Method)",
                     rb_obj_classname(body));
        }
    }
    if (!id) id = rb_to_id(name);

    if (is_method) {
        struct METHOD *method = (struct METHOD *)DATA_PTR(body);
        if (method->me->owner != mod && !RB_TYPE_P(method->me->owner, T_MODULE) &&
            !RTEST(rb_class_inherited_p(mod, method->me->owner))) {
            if (FL_TEST(method->me->owner, FL_SINGLETON)) {
                rb_raise(rb_eTypeError,
                         "can't bind singleton method to a different class");
            }
            else {
                rb_raise(rb_eTypeError,
                         "bind argument must be a subclass of % "PRIsVALUE,
                         rb_class_name(method->me->owner));
            }
        }
        rb_method_entry_set(mod, id, method->me, scope_visi->method_visi);
        if (scope_visi->module_func) {
            rb_method_entry_set(rb_singleton_class(mod), id, method->me, METHOD_VISI_PUBLIC);
        }
        RB_GC_GUARD(body);
    }
    else {
        VALUE procval = proc_dup(body);
        if (vm_proc_iseq(procval) != NULL) {
            rb_proc_t *proc;
            GetProcPtr(procval, proc);
            proc->is_lambda = TRUE;
            proc->is_from_method = TRUE;
        }
        rb_add_method(mod, id, VM_METHOD_TYPE_BMETHOD, (void *)procval, scope_visi->method_visi);
        if (scope_visi->module_func) {
            rb_add_method(rb_singleton_class(mod), id, VM_METHOD_TYPE_BMETHOD, (void *)body, METHOD_VISI_PUBLIC);
        }
    }

    return ID2SYM(id);
}

Определяет метод экземпляра в получателе. Параметр method может быть Proc, Method или объектом UnboundMethod. Если указан блок, он используется в качестве тела метода. Этот блок вычисляется с использованием instance_eval, что сложно продемонстрировать, поскольку define_method является приватным. (Поэтому мы прибегаем к send хаку в этом примере.)

class A
  def fred
    puts "In Fred"
  end
  def create_method(name, &block)
    self.class.send(:define_method, name, &block)
  end
  define_method(:wilma) { puts "Charge it!" }
end
class B < A
  define_method(:barney, instance_method(:fred))
end
a = B.new
a.barney
a.wilma
a.create_method(:betty) { p self }
a.betty

результат:

In Fred
Charge it!
#<B:0x401b39e8>
extend_object(obj) → obj Show source
static VALUE
rb_mod_extend_object(VALUE mod, VALUE obj)
{
    rb_extend_object(obj, mod);
    return obj;
}

Расширяет указанный объект, добавляя константы и методы этого модуля (которые добавляются как одиночные методы). Это метод обратного вызова, используемый Object#extend.

module Picky
  def Picky.extend_object(o)
    if String === o
      puts "Can't add Picky to a String"
    else
      puts "Picky added to #{o.class}"
      super
    end
  end
end
(s = Array.new).extend Picky  # Call Object.extend
(s = "quick brown fox").extend Picky

результат:

Picky added to Array
Can't add Picky to a String
extended(othermod) Show source
static VALUE
rb_obj_dummy(void)
{
    return Qnil;
}

Эквивалент included, но для расширенных модулей.

module A
  def self.extended(mod)
    puts "#{self} extended in #{mod}"
  end
end
module Enumerable
  extend A
end
 # => prints "A extended in Enumerable"
included(othermod) Show source
static VALUE
rb_obj_dummy(void)
{
    return Qnil;
}

Обратный вызов, вызываемый всякий раз, когда получатель включается в другой модуль или класс. Его следует использовать вместо Module.append_features, если ваш код должен выполнить какое-либо действие при включении модуля в другой.

module A
  def A.included(mod)
    puts "#{self} included in #{mod}"
  end
end
module Enumerable
  include A
end
 # => prints "A included in Enumerable"
method_added(method_name) Show source
static VALUE
rb_obj_dummy(void)
{
    return Qnil;
}

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

module Chatty
  def self.method_added(method_name)
    puts "Adding #{method_name.inspect}"
  end
  def self.some_class_method() end
  def some_instance_method() end
end

результат:

Adding :some_instance_method
method_removed(method_name) Show source
static VALUE
rb_obj_dummy(void)
{
    return Qnil;
}

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

module Chatty
  def self.method_removed(method_name)
    puts "Removing #{method_name.inspect}"
  end
  def self.some_class_method() end
  def some_instance_method() end
  class << self
    remove_method :some_class_method
  end
  remove_method :some_instance_method
end

результат:

Removing :some_instance_method
method_undefined(p1) Show source
static VALUE
rb_obj_dummy(void)
{
    return Qnil;
}

Не задокументировано

module_function(symbol, ...) → self Show source
module_function(string, ...) → self
static VALUE
rb_mod_modfunc(int argc, VALUE *argv, VALUE module)
{
    int i;
    ID id;
    const rb_method_entry_t *me;

    if (!RB_TYPE_P(module, T_MODULE)) {
        rb_raise(rb_eTypeError, "module_function must be called for modules");
    }

    if (argc == 0) {
        rb_scope_module_func_set();
        return module;
    }

    set_method_visibility(module, argc, argv, METHOD_VISI_PRIVATE);

    for (i = 0; i < argc; i++) {
        VALUE m = module;

        id = rb_to_id(argv[i]);
        for (;;) {
            me = search_method(m, id, 0);
            if (me == 0) {
                me = search_method(rb_cObject, id, 0);
            }
            if (UNDEFINED_METHOD_ENTRY_P(me)) {
                rb_print_undef(module, id, METHOD_VISI_UNDEF);
            }
            if (me->def->type != VM_METHOD_TYPE_ZSUPER) {
                break; /* normal case: need not to follow 'super' link */
            }
            m = RCLASS_SUPER(m);
            if (!m)
                break;
        }
        rb_method_entry_set(rb_singleton_class(module), id, me, METHOD_VISI_PUBLIC);
    }
    return module;
}

Создает функции модуля для указанных методов. Эти функции могут вызываться с модулем в качестве получателя, а также становятся доступными как методы экземпляра для классов, которые смешивают модуль. Функции модуля являются копиями оригинала и, следовательно, могут быть изменены независимо. Версии метода экземпляра делаются приватными. Если используется без аргументов, последующие определенные методы становятся функциями модуля. Аргументы типа строка преобразуются в символы.

module Mod
  def one
    "This is one"
  end
  module_function :one
end
class Cls
  include Mod
  def call_one
    one
  end
end
Mod.one     #=> "This is one"
c = Cls.new
c.call_one  #=> "This is one"
module Mod
  def one
    "This is the new one"
  end
end
Mod.one     #=> "This is one"
c.call_one  #=> "This is the new one"
prepend_features(mod) → mod Show source
static VALUE
rb_mod_prepend_features(VALUE module, VALUE prepend)
{
    if (!CLASS_OR_MODULE_P(prepend)) {
        Check_Type(prepend, T_CLASS);
    }
    rb_prepend_module(prepend, module);

    return module;
}

Когда этот модуль добавляется в начало другого, Ruby вызывает prepend_features в этом модуле, передавая ему принимающий модуль в mod. Реализация по умолчанию в Ruby заключается в наложении констант, методов и переменных модуля на mod, если этот модуль еще не был добавлен к mod или одному из его предков. См. также Module#prepend.

prepended(othermod) Show source
static VALUE
rb_obj_dummy(void)
{
    return Qnil;
}

Эквивалент included, но для модулей, добавленных в начало.

module A
  def self.prepended(mod)
    puts "#{self} prepended to #{mod}"
  end
end
module Enumerable
  prepend A
end
 # => prints "A prepended to Enumerable"
private → self Show source
private(symbol, ...) → self
private(string, ...) → self
static VALUE
rb_mod_private(int argc, VALUE *argv, VALUE module)
{
    return set_visibility(argc, argv, module, METHOD_VISI_PRIVATE);
}

Без аргументов устанавливает видимость по умолчанию для последующих определенных методов как приватную. С аргументами устанавливает для указанных методов приватную видимость. Аргументы типа строка преобразуются в символы.

module Mod
  def a()  end
  def b()  end
  private
  def c()  end
  private :a
end
Mod.private_instance_methods   #=> [:a, :c]

Обратите внимание, что для отображения приватного метода в RDoc, используйте :doc:.

protected → self Показать исходный код
protected(символ, ...) → self
protected(строка, ...) → self
static VALUE
rb_mod_protected(int argc, VALUE *argv, VALUE module)
{
    return set_visibility(argc, argv, module, METHOD_VISI_PROTECTED);
}

Без аргументов устанавливает видимость по умолчанию для последующих методов как защищенную. С аргументами устанавливает защищенную видимость для указанных методов. Строковые аргументы преобразуются в символы.

Если метод имеет защищенную видимость, он доступен только там, где self контекста совпадает с контекстом метода. (определение метода или instance_eval). Это поведение отличается от защищенного метода Java. Обычно private следует использовать.

Обратите внимание, что защищенный метод медленный, так как он не может использовать кеш.

Чтобы отобразить частный метод в RDoc, используйте :doc: вместо этого.

public → self Показать исходный код
public(символ, ...) → self
public(строка, ...) → self
static VALUE
rb_mod_public(int argc, VALUE *argv, VALUE module)
{
    return set_visibility(argc, argv, module, METHOD_VISI_PUBLIC);
}

Без аргументов устанавливает видимость по умолчанию для последующих методов как публичную. С аргументами устанавливает публичную видимость для указанных методов. Строковые аргументы преобразуются в символы.

refine(mod) { блок } → модуль Показать исходный код
static VALUE
rb_mod_refine(VALUE module, VALUE klass)
{
    VALUE refinement;
    ID id_refinements, id_activated_refinements,
       id_refined_class, id_defined_at;
    VALUE refinements, activated_refinements;
    rb_thread_t *th = GET_THREAD();
    VALUE block_handler = rb_vm_frame_block_handler(th->cfp);

    if (block_handler == VM_BLOCK_HANDLER_NONE) {
        rb_raise(rb_eArgError, "no block given");
    }
    if (vm_block_handler_type(block_handler) != block_handler_type_iseq) {
        rb_raise(rb_eArgError, "can't pass a Proc as a block to Module#refine");
    }

    ensure_class_or_module(klass);
    CONST_ID(id_refinements, "__refinements__");
    refinements = rb_attr_get(module, id_refinements);
    if (NIL_P(refinements)) {
        refinements = hidden_identity_hash_new();
        rb_ivar_set(module, id_refinements, refinements);
    }
    CONST_ID(id_activated_refinements, "__activated_refinements__");
    activated_refinements = rb_attr_get(module, id_activated_refinements);
    if (NIL_P(activated_refinements)) {
        activated_refinements = hidden_identity_hash_new();
        rb_ivar_set(module, id_activated_refinements,
                    activated_refinements);
    }
    refinement = rb_hash_lookup(refinements, klass);
    if (NIL_P(refinement)) {
        VALUE superclass = refinement_superclass(klass);
        refinement = rb_module_new();
        RCLASS_SET_SUPER(refinement, superclass);
        FL_SET(refinement, RMODULE_IS_REFINEMENT);
        CONST_ID(id_refined_class, "__refined_class__");
        rb_ivar_set(refinement, id_refined_class, klass);
        CONST_ID(id_defined_at, "__defined_at__");
        rb_ivar_set(refinement, id_defined_at, module);
        rb_hash_aset(refinements, klass, refinement);
        add_activated_refinement(activated_refinements, klass, refinement);
    }
    rb_yield_refine_block(refinement, activated_refinements);
    return refinement;
}

Уточнить mod в получателе.

Возвращает модуль, где определены уточненные методы.

remove_const(символ) → объект Показать исходный код
VALUE
rb_mod_remove_const(VALUE mod, VALUE name)
{
    const ID id = id_for_var(mod, name, a, constant);

    if (!id) {
	rb_name_err_raise("constant %2$s::%1$s not defined",
			  mod, name);
    }
    return rb_const_remove(mod, id);
}

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

remove_method(символ) → self Показать исходный код
remove_method(строка) → self
static VALUE
rb_mod_remove_method(int argc, VALUE *argv, VALUE mod)
{
    int i;

    for (i = 0; i < argc; i++) {
        VALUE v = argv[i];
        ID id = rb_check_id(&v);
        if (!id) {
            rb_name_err_raise("method `%1$s' not defined in %2$s",
                              mod, v);
        }
        remove_method(mod, id);
    }
    return mod;
}

Удаляет метод, идентифицированный символом, из текущего класса. Пример см. в Module.undef_method. Строковые аргументы преобразуются в символы.

undef_method(символ) → self Показать исходный код
undef_method(строка) → self
static VALUE
rb_mod_undef_method(int argc, VALUE *argv, VALUE mod)
{
    int i;
    for (i = 0; i < argc; i++) {
        VALUE v = argv[i];
        ID id = rb_check_id(&v);
        if (!id) {
            rb_method_name_error(mod, v);
        }
        rb_undef(mod, id);
    }
    return mod;
}

Запрещает текущему классу реагировать на вызовы указанного метода. Противопоставьте это remove_method, которое удаляет метод из конкретного класса; Ruby по-прежнему будет искать суперклассы и включаемые модули в поисках возможного получателя. Строковые аргументы преобразуются в символы.

class Parent
  def hello
    puts "In parent"
  end
end
class Child < Parent
  def hello
    puts "In child"
  end
end

c = Child.new
c.hello

class Child
  remove_method :hello  # remove from child, still in parent
end
c.hello

class Child
  undef_method :hello   # prevent any calls to 'hello'
end
c.hello

выводит:

In child
In parent
prog.rb:23: undefined method `hello' for #<Child:0x401b3bb4> (NoMethodError)
using(модуль) → self Показать исходный код
static VALUE
mod_using(VALUE self, VALUE module)
{
    rb_control_frame_t *prev_cfp = previous_frame(GET_THREAD());

    if (prev_frame_func()) {
        rb_raise(rb_eRuntimeError,
                 "Module#using is not permitted in methods");
    }
    if (prev_cfp && prev_cfp->self != self) {
        rb_raise(rb_eRuntimeError, "Module#using is not called on self");
    }
    if (rb_block_given_p()) {
        ignored_block(module, "Module#");
    }
    rb_using_module(rb_vm_cref_replace_with_duplicated_cref(), module);
    return self;
}

Импортировать улучшения класса из модуля в текущее определение класса или модуля.

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