class Object
Object 是所有 Ruby 对象的默认根。 Object 继承自 BasicObject,这允许创建替代的对象层级结构。除非被显式覆盖,否则 Object 上的方法对所有类都可用。
Object 混入了 Kernel 模块,使得内置的内核函数全局可访问。尽管 Object 的实例方法由 Kernel 模块定义,但为了清晰起见,我们选择在此处记录它们。
在引用继承自 Object 的类的常量时,您无需使用完整的命名空间。例如,在 YourClass 中引用 File 将找到顶层的 File 类。
在 Object 方法的描述中,参数 symbol 指的是一个符号(symbol),它可以是带引号的字符串或 Symbol(例如 :name)。
这里有什么
首先,这里是其他内容。Class Object
-
继承自 class BasicObject。
-
包含 module Kernel。
此处,class Object 提供了用于以下方法:
查询
-
!~: 如果self不匹配给定对象,则返回true,否则返回false。 -
<=>: 如果self和给定对象object是同一个对象,或者如果self == object,则返回 0;否则返回nil。 -
instance_of?: 返回self是否为给定类的实例。 -
instance_variable_defined?: 返回给定实例变量是否在self中定义。 -
methods: 返回self中公共(public)和受保护(protected)方法名称的符号数组。 -
nil?: 返回false。(只有nil对象对方法nil?返回true。) -
object_id: 返回一个与self对应的整数,该整数在当前进程中是唯一的。 -
private_methods: 返回self中私有(private)方法名称的符号数组。 -
protected_methods: 返回self中受保护(protected)方法名称的符号数组。 -
public_method: 返回self中给定公共(public)方法的Method对象。 -
public_methods: 返回self中公共(public)方法名称的符号数组。 -
respond_to?: 返回self是否响应给定方法。 -
singleton_class: 返回self的单例类。 -
singleton_method: 返回self中给定单例方法的Method对象。 -
singleton_methods: 返回self中单例方法名称的符号数组。 -
define_singleton_method: 为self定义一个单例方法,使用给定的符号方法名和块或 proc。 -
extend: 将给定的模块混入self的单例类。 -
public_send: 使用给定的参数调用self的公共方法。 -
send: 使用给定的参数调用self的方法。
实例变量
-
instance_variable_get: 返回self中给定实例变量的值,如果实例变量未设置,则返回nil。 -
instance_variable_set: 将self中给定实例变量的值设置为给定的对象。 -
instance_variables: 返回self中实例变量名称的符号数组。 -
remove_instance_variable: 从self中移除指定的实例变量。
其他
-
clone: 返回self的浅拷贝,包括单例类和冻结状态。 -
define_singleton_method: 为self定义一个单例方法,使用给定的符号方法名和块或 proc。 -
dup: 返回self的浅拷贝,未冻结。 -
enum_for(别名为to_enum): 返回一个Enumerator,用于self,通过使用给定的方法、参数和块。 -
extend: 将给定的模块混入self的单例类。 -
freeze: 防止对self进行进一步修改。 -
hash: 返回self的整数哈希值。 -
inspect: 返回self的人类可读的字符串表示形式。 -
itself: 返回self。 -
method_missing: 当在self上调用未定义的方法时调用的方法。 -
public_send: 使用给定的参数调用self的公共方法。 -
send: 使用给定的参数调用self的方法。 -
to_s: 返回self的字符串表示形式。
Constants
- ARGF
-
ARGF是一个流,用于处理作为命令行参数给出或通过STDIN传入的文件。该流旨在用于处理文件的脚本。请参阅
ARGF(类)了解更多详情。 - ARGV
-
ARGV包含运行 Ruby 的命令行参数。像
OptionParser这样的库可用于处理命令行参数。 - CROSS_COMPILING
-
如果在交叉编译配置中,则非 nil。
- DATA
-
DATA是一个File,包含已执行文件的数据部分。要创建数据部分,请使用__END__$ cat t.rb puts DATA.gets __END__ hello world! $ ruby t.rb hello world!
- ENV
-
ENV是一个类似 Hash 的环境变量访问器。请参阅
ENV(类)了解更多详情。 - Ripper
- STDERR
-
保存原始 stderr
- STDIN
-
保存原始 stdin
- STDOUT
-
保存原始 stdout
- TOPLEVEL_BINDING
-
顶层作用域的
Binding。
Public Class Methods
Source
# File ext/psych/lib/psych/core_ext.rb, line 3 def self.yaml_tag url Psych.add_tag(url, self) end
Public Instance Methods
Source
static VALUE
rb_obj_not_match(VALUE obj1, VALUE obj2)
{
VALUE result = rb_funcall(obj1, id_match, 1, obj2);
return rb_obj_not(result);
}
如果两个对象不匹配(使用 =~ 方法),则返回 true,否则返回 false。
Source
static VALUE
rb_obj_cmp(VALUE obj1, VALUE obj2)
{
if (rb_equal(obj1, obj2))
return INT2FIX(0);
return Qnil;
}
比较 self 和 other。
返回
-
0,如果self和other是同一个对象,或者如果self == other。 -
nil,否则。
示例
o = Object.new o <=> o # => 0 o <=> o.dup # => nil
包含模块 Comparable 的类应通过定义一个实例方法来覆盖此方法,该方法
-
接受一个参数
other。 -
返回
-
-1,如果self小于other。 -
0,如果self等于other。 -
1,如果self大于other。 -
nil,如果两个值无法比较。
-
Source
#define case_equal rb_equal
Source
# File lib/delegate.rb, line 395 def DelegateClass(superclass, &block) klass = Class.new(Delegator) ignores = [*::Delegator.public_api, :to_s, :inspect, :=~, :!~, :===] protected_instance_methods = superclass.protected_instance_methods protected_instance_methods -= ignores public_instance_methods = superclass.public_instance_methods public_instance_methods -= ignores normal, special = public_instance_methods.partition { |m| m.match?(/\A[a-zA-Z]\w*[!\?]?\z/) } source = normal.map do |method| "def #{method}(...); __getobj__.#{method}(...); end" end protected_instance_methods.each do |method| source << "def #{method}(...); __getobj__.__send__(#{method.inspect}, ...); end" end klass.module_eval do def __getobj__ # :nodoc: unless defined?(@delegate_dc_obj) return yield if block_given? __raise__ ::ArgumentError, "not delegated" end @delegate_dc_obj end def __setobj__(obj) # :nodoc: __raise__ ::ArgumentError, "cannot delegate to self" if self.equal?(obj) @delegate_dc_obj = obj end class_eval(source.join(";"), __FILE__, __LINE__) special.each do |method| define_method(method, Delegator.delegating_block(method)) end protected(*protected_instance_methods) end klass.define_singleton_method :public_instance_methods do |all=true| super(all) | superclass.public_instance_methods end klass.define_singleton_method :protected_instance_methods do |all=true| super(all) | superclass.protected_instance_methods end klass.define_singleton_method :instance_methods do |all=true| super(all) | superclass.instance_methods end klass.define_singleton_method :public_instance_method do |name| super(name) rescue NameError raise unless self.public_instance_methods.include?(name) superclass.public_instance_method(name) end klass.define_singleton_method :instance_method do |name| super(name) rescue NameError raise unless self.instance_methods.include?(name) superclass.instance_method(name) end klass.module_eval(&block) if block return klass end
此库的主要接口。用于在定义类时设置委托。
class MyClass < DelegateClass(ClassToDelegateTo) # Step 1 def initialize super(obj_of_ClassToDelegateTo) # Step 2 end end
或
MyClass = DelegateClass(ClassToDelegateTo) do # Step 1 def initialize super(obj_of_ClassToDelegateTo) # Step 2 end end
以下是来自 Tempfile 的使用示例,它实际上是一个 File 对象,具有一些关于存储位置和文件应何时删除的特殊规则。这使得它成为使用委托的近乎教科书般的完美示例。
class Tempfile < DelegateClass(File) # constant and class member data initialization... def initialize(basename, tmpdir=Dir::tmpdir) # build up file path/name in var tmpname... @tmpfile = File.open(tmpname, File::RDWR|File::CREAT|File::EXCL, 0600) # ... super(@tmpfile) # below this point, all methods of File are supported... end # ... end
Source
# File ext/digest/lib/digest.rb, line 110 def Digest(name) const = name.to_sym Digest::REQUIRE_MUTEX.synchronize { # Ignore autoload's because it is void when we have #const_missing Digest.const_missing(const) } rescue LoadError # Constants do not necessarily rely on digest/*. if Digest.const_defined?(const) Digest.const_get(const) else raise end end
以线程安全的方式返回按 name 排序的 Digest 子类,即使涉及按需加载。
require 'digest' Digest("MD5") # => Digest::MD5 Digest(:SHA256) # => Digest::SHA256 Digest(:Foo) # => LoadError: library not found for class Digest::Foo -- digest/foo
Source
static VALUE
rb_obj_define_method(int argc, VALUE *argv, VALUE obj)
{
VALUE klass = rb_singleton_class(obj);
const rb_scope_visibility_t scope_visi = {METHOD_VISI_PUBLIC, FALSE};
return rb_mod_define_method_with_visibility(argc, argv, klass, &scope_visi);
}
在接收者中定义一个公共单例方法。method 参数可以是 Proc、Method 或 UnboundMethod 对象。如果指定了块,则将其用作方法体。如果块或方法有参数,则将它们用作方法参数。
class A class << self def class_name to_s end end end A.define_singleton_method(:who_am_i) do "I am: #{class_name}" end A.who_am_i # ==> "I am: A" guy = "Bob" guy.define_singleton_method(:hello) { "#{self}: Hello there!" } guy.hello #=> "Bob: Hello there!" chris = "Chris" chris.define_singleton_method(:greet) {|greeting| "#{greeting}, I'm Chris!" } chris.greet("Hi") #=> "Hi, I'm Chris!"
Source
static VALUE
rb_obj_display(int argc, VALUE *argv, VALUE self)
{
VALUE out;
out = (!rb_check_arity(argc, 0, 1) ? rb_ractor_stdout() : argv[0]);
rb_io_write(out, self);
return Qnil;
}
将 self 写入指定的端口
1.display "cat".display [ 4, 5, 6 ].display puts
输出
1cat[4, 5, 6]
Source
VALUE
rb_obj_dup(VALUE obj)
{
VALUE dup;
if (special_object_p(obj)) {
return obj;
}
dup = rb_obj_alloc(rb_obj_class(obj));
return rb_obj_dup_setup(obj, dup);
}
生成 obj 的浅拷贝 — obj 的实例变量被复制,但它们引用的对象未被复制。
此方法可能具有特定于类的行为。如果是这样,该行为将在该类的 #initialize_copy 方法下进行记录。
关于 dup 和 clone
通常,clone 和 dup 在子类中可能有不同的语义。虽然 clone 用于复制对象(包括其内部状态),但 dup 通常使用子类对象的类来创建新实例。
使用 dup 时,对象已扩展的任何模块都不会被复制。
class Klass attr_accessor :str end module Foo def foo; 'foo'; end end s1 = Klass.new #=> #<Klass:0x401b3a38> s1.extend(Foo) #=> #<Klass:0x401b3a38> s1.foo #=> "foo" s2 = s1.clone #=> #<Klass:0x401be280> s2.foo #=> "foo" s3 = s1.dup #=> #<Klass:0x401c1084> s3.foo #=> NoMethodError: undefined method `foo' for #<Klass:0x401c1084>
创建一个新的 Enumerator,它将通过调用 obj 上的 method 来枚举,并传递任何 args。由 method yield 的内容将成为枚举器的值。
如果给出了块,它将用于计算枚举器的大小,而无需迭代它(请参阅 Enumerator#size)。
示例
str = "xyz" enum = str.enum_for(:each_byte) enum.each { |b| puts b } # => 120 # => 121 # => 122 # protect an array from being modified by some_method a = [1, 2, 3] some_method(a.to_enum) # String#split in block form is more memory-effective: very_large_string.split("|") { |chunk| return chunk if chunk.include?('DATE') } # This could be rewritten more idiomatically with to_enum: very_large_string.to_enum(:split, "|").lazy.grep(/DATE/).first
通常在为通用的 Enumerable 定义方法时调用 to_enum,以防没有传递块。
以下是一个此类示例,包含参数传递和大小块
module Enumerable # a generic method to repeat the values of any enumerable def repeat(n) raise ArgumentError, "#{n} is negative!" if n < 0 unless block_given? return to_enum(__method__, n) do # __method__ is :repeat here sz = size # Call size and multiply by n... sz * n if sz # but return nil if size itself is nil end end each do |*val| n.times { yield *val } end end end %i[hello world].repeat(2) { |w| puts w } # => Prints 'hello', 'hello', 'world', 'world' enum = (1..14).repeat(3) # => returns an Enumerator when called without a block enum.first(4) # => [1, 1, 1, 2] enum.size # => 42
Source
VALUE
rb_obj_equal(VALUE obj1, VALUE obj2)
{
return RBOOL(obj1 == obj2);
}
相等性 — 在 Object 级别,== 仅当 obj 和 other 是同一个对象时返回 true。通常,此方法会在子类中被覆盖,以提供特定于类的含义。
与 == 不同,equal? 方法不应由子类覆盖,因为它用于确定对象标识(即,当且仅当 a 和 b 是同一个对象时,a.equal?(b) 才为真)。
obj = "a" other = obj.dup obj == other #=> true obj.equal? other #=> false obj.equal? obj #=> true
eql? 方法在 obj 和 other 是否引用同一个哈希键时返回 true。这由 Hash 用于测试成员的相等性。对于任何一对 eql? 返回 true 的对象,这两个对象的 hash 值必须相等。因此,任何覆盖 eql? 的子类也应相应地覆盖 hash。
对于 Object 类的对象,eql? 与 == 同义。子类通常通过将 eql? 别名为其覆盖的 == 方法来延续这种传统,但也有例外。例如,Numeric 类型在 == 上执行类型转换,但在 eql? 上不执行,所以
1 == 1.0 #=> true 1.eql? 1.0 #=> false
Source
static VALUE
rb_obj_extend(int argc, VALUE *argv, VALUE obj)
{
int i;
ID id_extend_object, id_extended;
CONST_ID(id_extend_object, "extend_object");
CONST_ID(id_extended, "extended");
rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
for (i = 0; i < argc; i++) {
Check_Type(argv[i], T_MODULE);
if (FL_TEST(argv[i], RMODULE_IS_REFINEMENT)) {
rb_raise(rb_eTypeError, "Cannot extend object with refinement");
}
}
while (argc--) {
rb_funcall(argv[argc], id_extend_object, 1, obj);
rb_funcall(argv[argc], id_extended, 1, obj);
}
return obj;
}
将每个模块的实例方法添加到 obj 中,模块由参数给出。
module Mod def hello "Hello from Mod.\n" end end class Klass def hello "Hello from Klass.\n" end end k = Klass.new k.hello #=> "Hello from Klass.\n" k.extend(Mod) #=> #<Klass:0x401b3bc8> k.hello #=> "Hello from Mod.\n"
Source
VALUE
rb_obj_freeze(VALUE obj)
{
if (!OBJ_FROZEN(obj)) {
OBJ_FREEZE(obj);
if (SPECIAL_CONST_P(obj)) {
rb_bug("special consts should be frozen.");
}
}
return obj;
}
阻止对 obj 进行进一步修改。如果尝试修改,将引发 FrozenError。无法解冻一个已冻结的对象。另请参阅 Object#frozen?。
此方法返回 self。
a = [ "a", "b", "c" ] a.freeze a << "z"
产生
prog.rb:3:in `<<': can't modify frozen Array (FrozenError) from prog.rb:3
Source
VALUE
rb_obj_hash(VALUE obj)
{
long hnum = any_hash(obj, objid_hash);
return ST2FIX(hnum);
}
返回 self 的整数哈希值;它具有以下属性:如果 foo.eql?(bar) 则 foo.hash == bar.hash。
类 Hash 同时使用 hash 和 eql? 来确定用作哈希键的两个对象是否应被视为同一个键。超出 Integer 容量的哈希值在使用前会被截断。
许多核心类会覆盖方法 Object#hash;其他核心类(例如 Integer)会在内部计算哈希值,并且在用作哈希键时不会调用 hash 方法。
在为用户定义的类实现 hash 时,最佳做法是使用 Array#hash 并包含类名和实例变量中的重要值;这利用了该方法安全高效地生成哈希值的逻辑。
def hash [self.class, a, b, c].hash end
哈希值在 Ruby 的不同调用或实现之间可能有所不同。如果您需要在 Ruby 调用和实现之间保持稳定的哈希状标识符,请使用自定义方法来生成它们。
Source
static VALUE
rb_obj_inspect(VALUE obj)
{
VALUE ivars = rb_check_funcall(obj, id_instance_variables_to_inspect, 0, 0);
st_index_t n = 0;
if (UNDEF_P(ivars) || NIL_P(ivars)) {
n = rb_ivar_count(obj);
ivars = Qnil;
}
else if (RB_TYPE_P(ivars, T_ARRAY)) {
n = RARRAY_LEN(ivars);
}
else {
rb_raise(
rb_eTypeError,
"Expected #instance_variables_to_inspect to return an Array or nil, but it returned %"PRIsVALUE,
rb_obj_class(ivars)
);
}
if (n > 0) {
VALUE c = rb_class_name(CLASS_OF(obj));
VALUE args[2] = {
rb_sprintf("-<%"PRIsVALUE":%p", c, (void*)obj),
ivars
};
return rb_exec_recursive(inspect_obj, obj, (VALUE)args);
}
else {
return rb_any_to_s(obj);
}
}
返回一个包含 obj 可读表示的字符串。默认的 inspect 显示对象的类名、内存地址的编码以及实例变量及其值的列表(通过调用每个变量的 inspect)。用户定义的类应覆盖此方法以提供 obj 的更好表示。覆盖此方法时,它应返回一个编码与默认外部编码兼容的字符串。
[ 1, 2, 3..4, 'five' ].inspect #=> "[1, 2, 3..4, \"five\"]" Time.new.inspect #=> "2008-03-08 19:43:39 +0900" class Foo end Foo.new.inspect #=> "#<Foo:0x0300c868>" class Bar def initialize @bar = 1 end end Bar.new.inspect #=> "#<Bar:0x0300c868 @bar=1>"
如果 obj 响应 instance_variables_to_inspect,则只有返回数组中列出的实例变量才会包含在 inspect 字符串中。
class DatabaseConfig def initialize(host, user, password) @host = host @user = user @password = password end private def instance_variables_to_inspect = [:@host, :@user] end conf = DatabaseConfig.new("localhost", "root", "hunter2") conf.inspect #=> #<DatabaseConfig:0x0000000104def350 @host="localhost", @user="root">
Source
VALUE
rb_obj_is_instance_of(VALUE obj, VALUE c)
{
c = class_or_module_required(c);
return RBOOL(rb_obj_class(obj) == c);
}
如果 obj 是给定类的实例,则返回 true。另请参阅 Object#kind_of?。
class A; end class B < A; end class C < B; end b = B.new b.instance_of? A #=> false b.instance_of? B #=> true b.instance_of? C #=> false
Source
static VALUE
rb_obj_ivar_defined(VALUE obj, VALUE iv)
{
ID id = id_for_var(obj, iv, instance);
if (!id) {
return Qfalse;
}
return rb_ivar_defined(obj, id);
}
如果给定的实例变量在 obj 中定义,则返回 true。String 参数将被转换为符号。
class Fred def initialize(p1, p2) @a, @b = p1, p2 end end fred = Fred.new('cat', 99) fred.instance_variable_defined?(:@a) #=> true fred.instance_variable_defined?("@b") #=> true fred.instance_variable_defined?("@c") #=> false
Source
static VALUE
rb_obj_ivar_get(VALUE obj, VALUE iv)
{
ID id = id_for_var(obj, iv, instance);
if (!id) {
return Qnil;
}
return rb_ivar_get(obj, id);
}
返回给定实例变量的值,如果实例变量未设置,则返回 nil。对于常规实例变量,应包含变量名称中的 @ 部分。如果提供的符号不是有效的实例变量名称,则会引发 NameError 异常。String 参数将被转换为符号。
class Fred def initialize(p1, p2) @a, @b = p1, p2 end end fred = Fred.new('cat', 99) fred.instance_variable_get(:@a) #=> "cat" fred.instance_variable_get("@b") #=> 99
Source
static VALUE
rb_obj_ivar_set_m(VALUE obj, VALUE iv, VALUE val)
{
ID id = id_for_var(obj, iv, instance);
if (!id) id = rb_intern_str(iv);
return rb_ivar_set(obj, id, val);
}
将 symbol 指定的实例变量设置为给定的对象。这可能会绕过类作者设计的封装,因此应谨慎使用。该变量在调用此方法之前不必存在。如果实例变量名称是作为字符串传递的,则该字符串将被转换为符号。
class Fred def initialize(p1, p2) @a, @b = p1, p2 end end fred = Fred.new('cat', 99) fred.instance_variable_set(:@a, 'dog') #=> "dog" fred.instance_variable_set(:@c, 'cat') #=> "cat" fred.inspect #=> "#<Fred:0x401b3da8 @a=\"dog\", @b=99, @c=\"cat\">"
Source
VALUE
rb_obj_instance_variables(VALUE obj)
{
VALUE ary;
ary = rb_ary_new();
rb_ivar_foreach(obj, ivar_i, ary);
return ary;
}
返回接收者实例变量名称的数组。请注意,仅仅定义一个访问器并不会创建相应的实例变量。
class Fred attr_accessor :a1 def initialize @iv = 3 end end Fred.new.instance_variables #=> [:@iv]
如果 class 是 obj 的类,或者 class 是 obj 的超类之一或包含在 obj 中的模块,则返回 true。
module M; end class A include M end class B < A; end class C < B; end b = B.new b.is_a? A #=> true b.is_a? B #=> true b.is_a? C #=> false b.is_a? M #=> true b.kind_of? A #=> true b.kind_of? B #=> true b.kind_of? C #=> false b.kind_of? M #=> true
Source
static VALUE
rb_obj_itself(VALUE obj)
{
return obj;
}
返回接收者。
string = "my string" string.itself.object_id == string.object_id #=> true
Source
VALUE
rb_obj_is_kind_of(VALUE obj, VALUE c)
{
VALUE cl = CLASS_OF(obj);
RUBY_ASSERT(RB_TYPE_P(cl, T_CLASS));
// Fastest path: If the object's class is an exact match we know `c` is a
// class without checking type and can return immediately.
if (cl == c) return Qtrue;
// Note: YJIT needs this function to never allocate and never raise when
// `c` is a class or a module.
if (LIKELY(RB_TYPE_P(c, T_CLASS))) {
// Fast path: Both are T_CLASS
return class_search_class_ancestor(cl, c);
}
else if (RB_TYPE_P(c, T_ICLASS)) {
// First check if we inherit the includer
// If we do we can return true immediately
VALUE includer = RCLASS_INCLUDER(c);
if (cl == includer) return Qtrue;
// Usually includer is a T_CLASS here, except when including into an
// already included Module.
// If it is a class, attempt the fast class-to-class check and return
// true if there is a match.
if (RB_TYPE_P(includer, T_CLASS) && class_search_class_ancestor(cl, includer))
return Qtrue;
// We don't include the ICLASS directly, so must check if we inherit
// the module via another include
return RBOOL(class_search_ancestor(cl, RCLASS_ORIGIN(c)));
}
else if (RB_TYPE_P(c, T_MODULE)) {
// Slow path: check each ancestor in the linked list and its method table
return RBOOL(class_search_ancestor(cl, RCLASS_ORIGIN(c)));
}
else {
rb_raise(rb_eTypeError, "class or module required");
UNREACHABLE_RETURN(Qfalse);
}
}
如果 class 是 obj 的类,或者 class 是 obj 的超类之一或包含在 obj 中的模块,则返回 true。
module M; end class A include M end class B < A; end class C < B; end b = B.new b.is_a? A #=> true b.is_a? B #=> true b.is_a? C #=> false b.is_a? M #=> true b.kind_of? A #=> true b.kind_of? B #=> true b.kind_of? C #=> false b.kind_of? M #=> true
Source
VALUE
rb_obj_method(VALUE obj, VALUE vid)
{
return obj_method(obj, vid, FALSE);
}
在 obj 中查找名为 sym 的方法作为接收者,返回一个 Method 对象(或引发 NameError)。Method 对象充当 obj 对象实例的闭包,因此实例变量和 self 的值仍然可用。
class Demo def initialize(n) @iv = n end def hello() "Hello, @iv = #{@iv}" end end k = Demo.new(99) m = k.method(:hello) m.call #=> "Hello, @iv = 99" l = Demo.new('Fred') m = l.method("hello") m.call #=> "Hello, @iv = Fred"
请注意,Method 实现 to_proc 方法,这意味着它可与迭代器一起使用。
[ 1, 2, 3 ].each(&method(:puts)) # => prints 3 lines to stdout out = File.open('test.txt', 'w') [ 1, 2, 3 ].each(&out.method(:puts)) # => prints 3 lines to file require 'date' %w[2017-03-01 2017-03-02].collect(&Date.method(:parse)) #=> [#<Date: 2017-03-01 ((2457814j,0s,0n),+0s,2299161j)>, #<Date: 2017-03-02 ((2457815j,0s,0n),+0s,2299161j)>]
Source
VALUE
rb_obj_methods(int argc, const VALUE *argv, VALUE obj)
{
rb_check_arity(argc, 0, 1);
if (argc > 0 && !RTEST(argv[0])) {
return rb_obj_singleton_methods(argc, argv, obj);
}
return class_instance_method_list(argc, argv, CLASS_OF(obj), 1, ins_methods_i);
}
返回 obj 的公共和受保护方法的名称列表。这将包括 obj 的祖先中所有可访问的方法。如果可选参数为 false,则返回 obj 的公共和受保护单例方法的数组,该数组不包括包含在 obj 中的模块中的方法。
class Klass def klass_method() end end k = Klass.new k.methods[0..9] #=> [:klass_method, :nil?, :===, # :==~, :!, :eql? # :hash, :<=>, :class, :singleton_class] k.methods.length #=> 56 k.methods(false) #=> [] def k.singleton_method; end k.methods(false) #=> [:singleton_method] module M123; def m123; end end k.extend M123 k.methods(false) #=> [:singleton_method]
Source
VALUE
rb_false(VALUE obj)
{
return Qfalse;
}
只有对象 nil 对 nil? 返回 true。
Object.new.nil? #=> false nil.nil? #=> true
Source
VALUE
rb_obj_id(VALUE obj)
{
/* If obj is an immediate, the object ID is obj directly converted to a Numeric.
* Otherwise, the object ID is a Numeric that is a non-zero multiple of
* (RUBY_IMMEDIATE_MASK + 1) which guarantees that it does not collide with
* any immediates. */
return rb_find_object_id(rb_gc_get_objspace(), obj, object_id);
}
返回 obj 的整数标识符。
对于给定对象,在所有对 object_id 的调用中将返回相同的数字,并且没有两个活动对象会共享一个 ID。
注意:一些内置类的对象被重用以进行优化。例如立即值和冻结的字符串字面量。
BasicObject 实现 __id__,Kernel 实现 object_id。
立即值不是通过引用传递,而是通过值传递:nil、true、false、Fixnums、Symbols 和一些 Floats。
Object.new.object_id == Object.new.object_id # => false (21 * 2).object_id == (21 * 2).object_id # => true "hello".object_id == "hello".object_id # => false "hi".freeze.object_id == "hi".freeze.object_id # => true
Source
VALUE
rb_obj_private_methods(int argc, const VALUE *argv, VALUE obj)
{
return class_instance_method_list(argc, argv, CLASS_OF(obj), 1, ins_methods_priv_i);
}
返回 obj 可访问的私有方法列表。如果 all 参数设置为 false,则只列出接收者中的方法。
Source
VALUE
rb_obj_protected_methods(int argc, const VALUE *argv, VALUE obj)
{
return class_instance_method_list(argc, argv, CLASS_OF(obj), 1, ins_methods_prot_i);
}
返回 obj 可访问的受保护方法列表。如果 all 参数设置为 false,则只列出接收者中的方法。
Source
VALUE
rb_obj_public_method(VALUE obj, VALUE vid)
{
return obj_method(obj, vid, TRUE);
}
类似于 method,但只搜索公共方法。
Source
VALUE
rb_obj_public_methods(int argc, const VALUE *argv, VALUE obj)
{
return class_instance_method_list(argc, argv, CLASS_OF(obj), 1, ins_methods_pub_i);
}
返回 obj 可访问的公共方法列表。如果 all 参数设置为 false,则只列出接收者中的方法。
Source
static VALUE
rb_f_public_send(int argc, VALUE *argv, VALUE recv)
{
return send_internal_kw(argc, argv, recv, CALL_PUBLIC);
}
调用由 symbol 标识的方法,并向其传递任何指定的参数。与 send 不同,public_send 只调用公共方法。当方法由字符串标识时,该字符串将被转换为符号。
1.public_send(:puts, "hello") # causes NoMethodError
Source
VALUE
rb_obj_remove_instance_variable(VALUE obj, VALUE name)
{
const ID id = id_for_var(obj, name, an, instance);
// Frozen check comes here because it's expected that we raise a
// NameError (from the id_for_var check) before we raise a FrozenError
rb_check_frozen(obj);
if (id) {
VALUE val = rb_ivar_delete(obj, id, Qundef);
if (!UNDEF_P(val)) return val;
}
rb_name_err_raise("instance variable %1$s not defined",
obj, name);
UNREACHABLE_RETURN(Qnil);
}
从 obj 中移除指定的实例变量,并返回该变量的值。名称可以作为符号或字符串传递。
class Dummy attr_reader :var def initialize @var = 99 end def remove remove_instance_variable(:@var) end end d = Dummy.new d.var #=> 99 d.remove #=> 99 d.var #=> nil
Source
static VALUE
obj_respond_to(int argc, VALUE *argv, VALUE obj)
{
VALUE mid, priv;
ID id;
rb_execution_context_t *ec = GET_EC();
rb_scan_args(argc, argv, "11", &mid, &priv);
if (!(id = rb_check_id(&mid))) {
VALUE ret = basic_obj_respond_to_missing(ec, CLASS_OF(obj), obj,
rb_to_symbol(mid), priv);
if (UNDEF_P(ret)) ret = Qfalse;
return ret;
}
return RBOOL(basic_obj_respond_to(ec, obj, id, !RTEST(priv)));
}
如果 obj 响应给定方法,则返回 true。仅当可选的第二个参数求值为 true 时,私有和受保护的方法才会被包含在搜索中。
如果方法未实现(例如 Windows 上的 Process.fork,GNU/Linux 上的 File.lchmod 等),则返回 false。
如果方法未定义,则会调用 respond_to_missing? 方法并返回其结果。
当方法名称参数以字符串形式给出时,该字符串将被转换为符号。
Source
static VALUE
obj_respond_to_missing(VALUE obj, VALUE mid, VALUE priv)
{
return Qfalse;
}
不要直接使用此方法。
钩子方法,用于返回 obj 是否可以响应 id 方法。
当方法名称参数以字符串形式给出时,该字符串将被转换为符号。
请参阅 respond_to? 和 BasicObject 的示例。
Source
VALUE
rb_f_send(int argc, VALUE *argv, VALUE recv)
{
return send_internal_kw(argc, argv, recv, CALL_FCALL);
}
调用由 symbol 标识的方法,并向其传递任何指定的参数。当方法由字符串标识时,该字符串将被转换为符号。
BasicObject 实现 __send__,Kernel 实现 send。当 obj 具有与 send 相同的类名(如 Socket)时,__send__ 比 send 更安全。另请参阅 public_send。
class Klass def hello(*args) "Hello " + args.join(' ') end end k = Klass.new k.send :hello, "gentle", "readers" #=> "Hello gentle readers"
Source
static VALUE
rb_obj_singleton_class(VALUE obj)
{
return rb_singleton_class(obj);
}
Source
VALUE
rb_obj_singleton_method(VALUE obj, VALUE vid)
{
VALUE sc = rb_singleton_class_get(obj);
VALUE klass;
ID id = rb_check_id(&vid);
if (NIL_P(sc) ||
NIL_P(klass = RCLASS_ORIGIN(sc)) ||
!NIL_P(rb_special_singleton_class(obj))) {
/* goto undef; */
}
else if (! id) {
VALUE m = mnew_missing_by_name(klass, obj, &vid, FALSE, rb_cMethod);
if (m) return m;
/* else goto undef; */
}
else {
VALUE args[2] = {obj, vid};
VALUE ruby_method = rb_rescue(rb_obj_singleton_method_lookup, (VALUE)args, rb_obj_singleton_method_lookup_fail, Qfalse);
if (ruby_method) {
struct METHOD *method = (struct METHOD *)RTYPEDDATA_GET_DATA(ruby_method);
VALUE lookup_class = RBASIC_CLASS(obj);
VALUE stop_class = rb_class_superclass(sc);
VALUE method_class = method->iclass;
/* Determine if method is in singleton class, or module included in or prepended to it */
do {
if (lookup_class == method_class) {
return ruby_method;
}
lookup_class = RCLASS_SUPER(lookup_class);
} while (lookup_class && lookup_class != stop_class);
}
}
/* undef: */
vid = ID2SYM(id);
rb_name_err_raise("undefined singleton method '%1$s' for '%2$s'",
obj, vid);
UNREACHABLE_RETURN(Qundef);
}
类似于 method,但只搜索单例方法。
class Demo def initialize(n) @iv = n end def hello() "Hello, @iv = #{@iv}" end end k = Demo.new(99) def k.hi "Hi, @iv = #{@iv}" end m = k.singleton_method(:hi) m.call #=> "Hi, @iv = 99" m = k.singleton_method(:hello) #=> NameError
Source
VALUE
rb_obj_singleton_methods(int argc, const VALUE *argv, VALUE obj)
{
VALUE ary, klass, origin;
struct method_entry_arg me_arg;
struct rb_id_table *mtbl;
int recur = TRUE;
if (rb_check_arity(argc, 0, 1)) recur = RTEST(argv[0]);
if (RCLASS_SINGLETON_P(obj)) {
rb_singleton_class(obj);
}
klass = CLASS_OF(obj);
origin = RCLASS_ORIGIN(klass);
me_arg.list = st_init_numtable();
me_arg.recur = recur;
if (klass && RCLASS_SINGLETON_P(klass)) {
if ((mtbl = RCLASS_M_TBL(origin)) != 0) rb_id_table_foreach(mtbl, method_entry_i, &me_arg);
klass = RCLASS_SUPER(klass);
}
if (recur) {
while (klass && (RCLASS_SINGLETON_P(klass) || RB_TYPE_P(klass, T_ICLASS))) {
if (klass != origin && (mtbl = RCLASS_M_TBL(klass)) != 0) rb_id_table_foreach(mtbl, method_entry_i, &me_arg);
klass = RCLASS_SUPER(klass);
}
}
ary = rb_ary_new2(me_arg.list->num_entries);
st_foreach(me_arg.list, ins_methods_i, ary);
st_free_table(me_arg.list);
return ary;
}
返回 obj 的单例方法名称数组。如果可选的 all 参数为 true,则列表将包括包含在 obj 中的模块中的方法。仅返回公共和受保护的单例方法。
module Other def three() end end class Single def Single.four() end end a = Single.new def a.one() end class << a include Other def two() end end Single.singleton_methods #=> [:four] a.singleton_methods(false) #=> [:two, :one] a.singleton_methods #=> [:two, :one, :three]
Source
static VALUE
obj_to_enum(int argc, VALUE *argv, VALUE obj)
{
VALUE enumerator, meth = sym_each;
if (argc > 0) {
--argc;
meth = *argv++;
}
enumerator = rb_enumeratorize_with_size(obj, meth, argc, argv, 0);
if (rb_block_given_p()) {
RB_OBJ_WRITE(enumerator, &enumerator_ptr(enumerator)->size, rb_block_proc());
}
return enumerator;
}
创建一个新的 Enumerator,它将通过调用 obj 上的 method 来枚举,并传递任何 args。由 method yield 的内容将成为枚举器的值。
如果给出了块,它将用于计算枚举器的大小,而无需迭代它(请参阅 Enumerator#size)。
示例
str = "xyz" enum = str.enum_for(:each_byte) enum.each { |b| puts b } # => 120 # => 121 # => 122 # protect an array from being modified by some_method a = [1, 2, 3] some_method(a.to_enum) # String#split in block form is more memory-effective: very_large_string.split("|") { |chunk| return chunk if chunk.include?('DATE') } # This could be rewritten more idiomatically with to_enum: very_large_string.to_enum(:split, "|").lazy.grep(/DATE/).first
通常在为通用的 Enumerable 定义方法时调用 to_enum,以防没有传递块。
以下是一个此类示例,包含参数传递和大小块
module Enumerable # a generic method to repeat the values of any enumerable def repeat(n) raise ArgumentError, "#{n} is negative!" if n < 0 unless block_given? return to_enum(__method__, n) do # __method__ is :repeat here sz = size # Call size and multiply by n... sz * n if sz # but return nil if size itself is nil end end each do |*val| n.times { yield *val } end end end %i[hello world].repeat(2) { |w| puts w } # => Prints 'hello', 'hello', 'world', 'world' enum = (1..14).repeat(3) # => returns an Enumerator when called without a block enum.first(4) # => [1, 1, 1, 2] enum.size # => 42
Source
VALUE
rb_any_to_s(VALUE obj)
{
VALUE str;
VALUE cname = rb_class_name(CLASS_OF(obj));
str = rb_sprintf("#<%"PRIsVALUE":%p>", cname, (void*)obj);
return str;
}
返回 obj 的字符串表示。默认的 to_s 会打印对象的类名和对象 ID 的编码。作为一种特殊情况,Ruby 程序的初始执行上下文的顶层对象返回“main”。
Source
# File ext/psych/lib/psych/core_ext.rb, line 12 def to_yaml options = {} Psych.dump self, options end
将对象转换为 YAML。有关可用的 options 的更多信息,请参阅 Psych.dump。