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