在线文档教程
Ruby 2.4

Module

Module类

Parent:Object

模块是方法和常量的集合。 模块中的方法可以是实例方法或模块方法。 当包含模块时,实例方法在类中显示为方法,而模块方法则不会。 相反,可以调用模块方法而不创建封装对象,而实例方法可能不会。 (请参阅Module#module_function。)

在下面的描述中,参数sym是指一个符号,它可以是带引号的字符串,也可以是符号(如:name)。

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

公共类方法

constants → array Show source

constants(inherited) → array

在第一种形式中,返回从调用点可访问的所有常量的名称数组。此列表包含全局范围中定义的所有模块和类的名称。

Module.constants.first(4) # => [:ARGF, :ARGV, :ArgumentError, :Array] Module.constants.include?(:SEEK_SET) # => false class IO Module.constants.include?(:SEEK_SET) # => true end

第二种形式调用实例方法常量。

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 }

nesting → array Show source

返回嵌套在调用点的模块列表。

module M1 module M2 $a = Module.nesting end end $a #=> [M1::M2, M1] $a[0].name #=> "M1::M2"

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; }

new → mod Show source

new {|mod| block } → mod

创建一个新的匿名模块。 如果给出了一个块,它将被传递给模块对象,并且该块将在该模块的上下文中进行评估,如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"

如果你想像常规模块那样把模块分配给一个常量(名字大写)。

static VALUE rb_mod_initialize(VALUE module) { if (rb_block_given_p()) { rb_mod_module_exec(1, &module, module } return Qnil; }

used_modules → array Show source

返回当前作用域中使用的所有模块的数组。未定义结果数组中模块的排序。

module A refine Object do end end module B refine Object do end end using A using B p Module.used_modules

生成结果:

[B, A]

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 }

公共实例方法

mod < other → true, false, or nil Show source

如果mod 是其他的子类,则返回true 。如果两者之间没有关系,则返回零。(根据类定义考虑关系:“A类<B”意味着“A <B”。)

static VALUE rb_mod_lt(VALUE mod, VALUE arg) { if (mod == arg) return Qfalse; return rb_class_inherited_p(mod, arg }

mod <= other → true, false, or nil Show source

如果mod是其他的子类或与其他子类相同,则返回true。 如果两者之间没有关系,则返回nil。 (根据类定义考虑关系:“A类<B”意味着“A <B”。)

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; }

module <=> other_module → -1, 0, +1, or nil Show source

比较返回-1,0,+1或nil,取决于模块是否包含other_module,它们是否相同,或者模块是否被other_module包含。

如果模块与other_module没有关系,则返回nil,如果other_module不是模块,或者两个值不可比较,则返回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 }

obj == other → true or false Show source

equal?(other) → true or false

eql?(other) → true or false

Equality - 在对象级别,==只有在obj和其他对象相同时才返回true。 通常,这个方法在后代类中被覆盖以提供类特定的含义。

不像==,equal?方法不应被子类覆盖,因为它用于确定对象标识(即a.equal?(b)当且仅当a与b相同时):

obj = "a" other = obj.dup obj == other #=> true obj.equal? other #=> false obj.equal? obj #=> true

如果obj和其他引用相同的散列键,则eql? 方法返回true(如果obj和其他引用相同的散列键)。 Hash使用它来测试成员是否相等。 对于Object类的对象,eql? 与==同义。 子类通常通过别名eql来继承这个传统? 到他们重写的==方法,但也有例外。 例如,数字类型通过==执行类型转换,但不通过eql?执行类型转换,因此:

1 == 1.0 #=> true 1.eql? 1.0 #=> false

VALUE rb_obj_equal(VALUE obj1, VALUE obj2) { if (obj1 == obj2) return Qtrue; return Qfalse; }

mod === obj → true or false Show source

Case Equality - 如果obj是mod的实例或mod的后代之一的实例,则返回true。 模块的用途有限,但可用于case语句以按类别对对象进行分类。

static VALUE rb_mod_eqq(VALUE mod, VALUE arg) { return rb_obj_is_kind_of(arg, mod }

mod > other → true, false, or nil Show source

如果mod是其他人的父类,则返回true。 如果两者之间没有关系,则返回nil。 (根据类定义考虑关系:“A类<B”意味着“B> A”。)

static VALUE rb_mod_gt(VALUE mod, VALUE arg) { if (mod == arg) return Qfalse; return rb_mod_ge(mod, arg }

mod >= other → true, false, or nil Show source

如果mod是其他父类,或者两个模块相同,则返回true。 如果两者之间没有关系,则返回nil。 (根据类定义考虑关系:“A类<B”意味着“B> A”。)

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 }

ancestors → array Show source

返回mod中 包含/预置的模块列表(包括mod本身)。

module Mod include Math include Comparable prepend Enumerable end Mod.ancestors #=> [Enumerable, Mod, Comparable, Math] Math.ancestors #=> [Math] Enumerable.ancestors #=> [Enumerable]

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; }

autoload(module, filename) → nil Show source

在mod的命名空间中首次访问该模块(可以是字符串或符号)时,注册要加载的文件名(使用Kernel :: require)。

module A end A.autoload(:B, "b") A::B.doit # autoloads "b"

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; }

autoload?(name) → String or nil Show source

如果名称在mod的命名空间中注册为autoload,则返回要加载的文件名。

module A end A.autoload(:B, "b") A.autoload?(:B) #=> "b"

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 }

class_eval(string [, filename , lineno]) → obj Show source

class_eval {|mod| block } → obj

评估mod上下文中的字符串或块,除非给定块时,常量/类变量查找不受影响。 这可以用来将方法添加到类中。 module_eval返回评估其参数的结果。 可选的文件名和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

VALUE rb_mod_module_eval(int argc, const VALUE *argv, VALUE mod) { return specific_eval(argc, argv, mod, mod }

class_exec(arg...) {|var...| block } → obj Show source

在类/模块的上下文中评估给定的块。该块中定义的方法将属于接收方。传递给该方法的任何参数都将传递给该块。如果该块需要访问实例变量,则可以使用该功能。

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

生成结果:

Hello there!

VALUE rb_mod_module_exec(int argc, const VALUE *argv, VALUE mod) { return yield_under(mod, mod, argc, argv }

class_variable_defined?(symbol) → true or false Show source

class_variable_defined?(string) → true or false

如果给定的类变量在obj中定义,则返回true。 字符串参数被转换为符号。

class Fred @@foo = 99 end Fred.class_variable_defined?(:@@foo) #=> true Fred.class_variable_defined?(:@@bar) #=> 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 }

class_variable_get(symbol) → obj Show source

class_variable_get(string) → obj

返回给定类变量的值(或引发NameError异常)。 变量名的@@部分应包含在常规类变量中。 字符串参数被转换为符号。

class Fred @@foo = 99 end Fred.class_variable_get(:@@foo) #=> 99

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 }

class_variable_set(symbol, obj) → obj Show source

class_variable_set(string, obj) → obj

将由符号 命名的类变量设置为给定的对象。如果类变量名称作为字符串传递,则该字符串将转换为符号。

class Fred @@foo = 99 def foo @@foo end end Fred.class_variable_set(:@@foo, 101) #=> 101 Fred.new.foo #=> 101

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; }

class_variables(inherit=true) → array Show source

返回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]

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 }

const_defined?(sym, inherit=true) → true or false Show source

const_defined?(str, inherit=true) → true or false

辨别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,并显示消息“错误的常量名称”:

Hash.const_defined? 'foobar' #=> NameError: wrong constant name foobar

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; }

const_get(sym, inherit=true) → obj Show source

const_get(str, inherit=true) → obj

检查mod中给定名称的常量。 如果设置了继承,查找还将搜索父类(如果mod是模块,则为对象)。

如果找到定义,则返回常量的值,否则会引发NameError。

Math.const_get(:PI) #=> 3.14159265358979

如果提供名称空间类名,此方法将递归查找常量名。例如:

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

每次查找时都会遵守继承标志。 例如:

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

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; }

const_missing(sym) → obj Show source

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

VALUE rb_mod_const_missing(VALUE klass, VALUE name) { rb_vm_pop_cfunc_frame( uninitialized_constant(klass, name UNREACHABLE; }

const_set(sym, obj) → obj Show source

const_set(str, obj) → obj

将指定的常量设置为给定对象,并返回该对象。如果先前不存在具有给定名称的常量,则创建一个新常量。

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

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; }

constants(inherit=true) → array Show source

返回在mod中可访问的常量的名称数组。 这包括任何包含模块中的常量名称(示例在开始部分),除非inherit参数设置为false。

实现不保证常量的顺序。

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

另见Module::const_defined?

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 } }

deprecate_constant(symbol, ...) → mod Show source

制作不支持使用的现有常量列表。

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 Show source

阻止对mod的 进一步修改。

此方法返回自身。

static VALUE rb_mod_freeze(VALUE mod) { rb_class_name(mod return rb_obj_freeze(mod }

include(module, ...) → self Show source

Module.append_features以相反的顺序调用每个参数。

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; }

include?(module) → true or false Show source

如果模组包含在mod或mod的祖先中,则返回true。

module A end class B include A end class C < B end B.include?(A) #=> true C.include?(A) #=> true A.include?(A) #=> 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; }

included_modules → array Show source

返回mod中 包含的模块列表。

module Mixin end module Outer include Mixin end Mixin.included_modules #=> [] Outer.included_modules #=> [Mixin]

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; }

inspect()

Alias for: to_s

instance_method(symbol) → unbound_method Show source

返回代表mod中给定实例方法的UnboundMethod。

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!

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 }

instance_methods(include_super=true) → array Show source

返回包含接收器中公共和受保护实例方法名称的数组。 对于一个模块,这些是公共和受保护的方法; 对于一个类,它们是实例(而不是单例)方法。 如果可选参数为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

VALUE rb_class_instance_methods(int argc, const VALUE *argv, VALUE mod) { return class_instance_method_list(argc, argv, mod, 0, ins_methods_i }

method_defined?(symbol) → true or false Show source

method_defined?(string) → true or false

如果命名方法由mod(或其包含的模块,如果mod是一个类,它的祖先)定义,则返回true。 公共和受保护的方法相匹配。 字符串参数被转换为符号。

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

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; }

module_eval(string [, filename , lineno]) → obj Show source

module_eval {|mod| block } → obj

评估mod上下文中的字符串或块,除非给定块时,常量/类变量查找不受影响。 这可以用来将方法添加到类中。 module_eval返回评估其参数的结果。 可选的文件名和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

VALUE rb_mod_module_eval(int argc, const VALUE *argv, VALUE mod) { return specific_eval(argc, argv, mod, mod }

module_exec(arg...) {|var...| block } → obj Show source

在类/模块的上下文中评估给定的块。该块中定义的方法将属于接收方。传递给该方法的任何参数都将传递给该块。如果该块需要访问实例变量,则可以使用该功能。

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

生成结果:

Hello there!

VALUE rb_mod_module_exec(int argc, const VALUE *argv, VALUE mod) { return yield_under(mod, mod, argc, argv }

name → string Show source

返回模块mod 的名称。匿名模块返回nil。

VALUE rb_mod_name(VALUE mod) { int permanent; VALUE path = classname(mod, &permanent if (!NIL_P(path)) return rb_str_dup(path return path; }

prepend(module, ...) → self Show source

以相反顺序在每个参数上调用Module.prepend_features。

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; }

private_class_method(symbol, ...) → mod Show source

private_class_method(string, ...) → mod

使现有的类方法保密。 通常用于隐藏新的默认构造函数。

字符串参数被转换为符号。

class SimpleSingleton # Not thread safe private_class_method :new def SimpleSingleton.create(*args, &block) @me = new(*args, &block) if ! @me @me end end

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; }

private_constant(symbol, ...) → mod Show source

使现有常量的列表保密。

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) → array Show source

返回mod中定义的私有实例方法的列表。 如果可选参数为false,则不包括任何父类的方法。

module Mod def method1() end private :method1 def method2() end end Mod.instance_methods #=> [:method2] Mod.private_instance_methods #=> [:method1]

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 }

private_method_defined?(symbol) → true or false Show source

private_method_defined?(string) → true or false

如果指定的私有方法由_ mod_(或其包含的模块以及如果mod是一个类,它的祖先)定义,则返回true。 字符串参数被转换为符号。

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

static VALUE rb_mod_private_method_defined(VALUE mod, VALUE mid) { return check_definition(mod, mid, METHOD_VISI_PRIVATE }

protected_instance_methods(include_super=true) → array Show source

返回mod中定义的受保护实例方法的列表。 如果可选参数为false,则不包括任何父类的方法。

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 }

protected_method_defined?(symbol) → true or false Show source

protected_method_defined?(string) → true or false

如果命名的protected方法由mod(或其包含的模块,以及如果mod是一个类,它的父类)定义,则返回true。 字符串参数被转换为符号。

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

static VALUE rb_mod_protected_method_defined(VALUE mod, VALUE mid) { return check_definition(mod, mid, METHOD_VISI_PROTECTED }

psych_yaml_as(url) Show source

# 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(symbol, ...) → mod Show source

public_class_method(string, ...) → 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(symbol, ...) → mod Show source

使现有的常量列表公开。

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(symbol) → unbound_method Show source

instance_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 }

public_instance_methods(include_super=true) → array Show source

返回mod中定义的公共实例方法的列表。 如果可选参数为false,则不包括任何父类的方法。

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 }

public_method_defined?(symbol) → true or false Show source

public_method_defined?(string) → true or false

如果命名的公共方法由mod(或其包含的模块,以及如果mod是一个类,它的祖先)定义,则返回true。 字符串参数被转换为符号。

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

static VALUE rb_mod_public_method_defined(VALUE mod, VALUE mid) { return check_definition(mod, mid, METHOD_VISI_PUBLIC }

remove_class_variable(sym) → obj Show source

删除sym的定义,返回该常量的值。

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

生成结果:

99 nil

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; }

singleton_class? → true or false Show source

如果mod是单例类,则返回true;如果是普通类或模块,则返回false。

class C end C.singleton_class? #=> false C.singleton_class.singleton_class? #=> true

static VALUE rb_mod_singleton_p(VALUE klass) { if (RB_TYPE_P(klass, T_CLASS) && FL_TEST(klass, FL_SINGLETON)) return Qtrue; return Qfalse; }

to_s → string Show source

返回表示此模块或类的字符串。对于基本类和模块,这是名称。对于单式,我们也会显示关于我们所附的东西的信息。

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

使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

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; }

append_features(mod) → mod Show source

当这个模块被包含在另一个模块中时,Ruby在这个模块中调用append_features,将模块中的接收模块传递给它。 Ruby的默认实现是将此模块的常量,方法和模块变量添加到mod,如果这个模块尚未添加到mod或其父类之一。 另请参阅模块#include。

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; }

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

为该模块定义一个命名属性,其名称为symbol.id2name,创建一个实例变量(@name)和一个相应的访问方法来读取它。 还创建一个名为name =的方法来设置属性。 字符串参数被转换为符号。

module Mod attr_accessor(:one, :two) end Mod.instance_methods.sort #=> [:one, :one=, :two, :two=]

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; }

attr_reader(symbol, ...) → nil Show source

attr(symbol, ...) → nil

attr_reader(string, ...) → nil

attr(string, ...) → nil

创建实例变量和相应的方法,以返回每个实例变量的值。 相当于依次在每个名称上调用“attr:name”。 字符串参数被转换为符号。

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_writer(symbol, ...) → nil Show source

attr_writer(string, ...) → nil

创建一个访问器方法,以允许分配给属性symbol.id2name。 字符串参数被转换为符号。

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; }

define_method(symbol, method) → symbol Show source

define_method(symbol) { block } → symbol

在接收器中定义一个实例方法。 方法参数可以是Proc,Method或UnboundMethod对象。 如果指定了块,则将其用作方法主体。 该块使用instance_eval进行评估,这是一个棘手的问题,因为define_method是私有的。 (这就是为什么我们在这个例子中使用发送黑客的原因。)

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>

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 }

extend_object(obj) → obj Show source

通过添加此模块的常量和方法(作为单例方法添加)来扩展指定的对象。 这是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

static VALUE rb_mod_extend_object(VALUE mod, VALUE obj) { rb_extend_object(obj, mod return obj; }

extended(othermod) Show source

相当于included,但扩展了模块。

module A def self.extended(mod) puts "#{self} extended in #{mod}" end end module Enumerable extend A end # => prints "A extended in Enumerable"

static VALUE rb_obj_dummy(void) { return Qnil; }

included(othermod) Show source

每当接收器被包含在另一个模块或类中时调用回调。 如果您的代码想要在另一个模块中包含某个模块时执行某些操作,则应该优先使用此模式。

module A def A.included(mod) puts "#{self} included in #{mod}" end end module Enumerable include A end # => prints "A included in Enumerable"

static VALUE rb_obj_dummy(void) { return Qnil; }

method_added(method_name) Show source

每当将实例方法添加到接收方时调用回调。

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

static VALUE rb_obj_dummy(void) { return Qnil; }

method_removed(method_name) Show source

每当一个实例方法从接收器中移除时,作为回调调用。

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

static VALUE rb_obj_dummy(void) { return Qnil; }

method_undefined(p1) Show source

没有记录

static VALUE rb_obj_dummy(void) { return Qnil; }

module_function(symbol, ...) → self Show source

module_function(string, ...) → self

为命名方法创建模块函数。 这些函数可以作为接收器模块调用,也可以作为模块中混合类的实例方法使用。 模块功能是原件的副本,因此可以独立更改。 实例方法版本是私有的。 如果不带参数使用,随后定义的方法将成为模块函数。 字符串参数被转换为符号。

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"

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; }

prepend_features(mod) → mod Show source

当这个模块在另一个模块中时,Ruby在这个模块中调用prepend_features,将模块中的接收模块传递给它。 Ruby的默认实现是将此模块的常量,方法和模块变量覆盖为mod,前提是该模块尚未添加到mod或其父类之一。 另请参见Module#prepend。

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; }

prepended(othermod) Show source

相当于included,但用于前置模块。

module A def self.prepended(mod) puts "#{self} prepended to #{mod}" end end module Enumerable prepend A end # => prints "A prepended to Enumerable"

static VALUE rb_obj_dummy(void) { return Qnil; }

private → self Show source

private(symbol, ...) → self

private(string, ...) → self

在没有参数的情况下,将随后定义的方法的默认可见性设置为私有。使用参数,将命名方法设置为具有私密可见性。字符串参数被转换为符号。

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

请注意,要在RDoc上显示私有方法,请使用:doc:

static VALUE rb_mod_private(int argc, VALUE *argv, VALUE module) { return set_visibility(argc, argv, module, METHOD_VISI_PRIVATE }

protected → self Show source

protected(symbol, ...) → self

protected(string, ...) → self

如果没有参数,则为随后定义的方法设置保护的默认可见性。使用参数,将命名方法设置为具有受保护的可见性。字符串参数被转换为符号。

如果方法具有受保护的可见性,则只有在上下文自身与方法相同的情况下才可调用该方法。 (方法定义或instance_eval)。 这种行为与Java的受保护方法不同。 通常应该使用私人的。

请注意,受保护的方法速度较慢,因为它不能使用内联缓存。

要在RDoc上显示私有方法,请使用:doc:而非这个。

static VALUE rb_mod_protected(int argc, VALUE *argv, VALUE module) { return set_visibility(argc, argv, module, METHOD_VISI_PROTECTED }

public → self Show source

public(symbol, ...) → self

public(string, ...) → self

在没有参数的情况下,将随后定义的方法的默认可见性设置为public。使用参数,可以将命名方法设置为公开可见性。字符串参数被转换为符号。

static VALUE rb_mod_public(int argc, VALUE *argv, VALUE module) { return set_visibility(argc, argv, module, METHOD_VISI_PUBLIC }

refine(mod) { block } → module Show source

在接收器中优化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)) { refinement = rb_module_new( RCLASS_SET_SUPER(refinement, klass 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; }

remove_const(sym) → obj Show source

除去给定常量的定义,返回该常量的前一个值。如果这个常量指向一个模块,这不会改变该模块的名称,并可能导致混淆。

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(symbol) → self Show source

remove_method(string) → self

从当前类中删除由符号标识的方法。 有关示例,请参阅Module.undef_method。 字符串参数被转换为符号。

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; }

undef_method(symbol) → self Show source

undef_method(string) → self

阻止当前类响应对指定方法的调用。 将其与remove_method相比较,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)

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; }

using(module) → self Show source

模块中的 类精简导入当前类或模块定义。

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; }