类 Object

Object 是所有 Ruby 对象的默认根类。 Object 继承自 BasicObject,允许创建替代的对象层次结构。 Object 上的方法对所有类都可用,除非被明确覆盖。

Object 混合了 Kernel 模块,使内置的内核函数全局可用。 虽然 Object 的实例方法是由 Kernel 模块定义的,但为了清晰起见,我们选择在这里记录它们。

在引用继承自 Object 的类的常量时,您不需要使用完整的命名空间。 例如,在 YourClass 中引用 File 将找到顶级的 File 类。

在 Object 方法的描述中,参数 symbol 指的是一个符号,它可以是带引号的字符串或 Symbol(例如 :name)。

这里有什么

首先,其他地方有什么。类 Object

这里,类 Object 提供了以下方法

查询

  • #!~: 如果 self 与给定对象不匹配,则返回 true,否则返回 false

  • #<=>: 如果 self 和给定对象 object 是同一个对象,或者 self == object,则返回 0;否则返回 nil

  • ===: 实现 case 等式,实际上与调用 == 相同。

  • eql?: 实现哈希相等性,实际上与调用 == 相同。

  • kind_of? (别名为 is_a?): 返回给定参数是否为 self 的单例类的祖先。

  • instance_of?: 返回 self 是否为给定类的实例。

  • instance_variable_defined?: 返回给定的实例变量是否在 self 中定义。

  • method: 返回 self 中给定方法的 Method 对象。

  • methods: 返回 self 中公共和受保护方法的符号名称数组。

  • nil?: 返回 false。 (只有 nil 对方法 nil? 返回 true。)

  • object_id: 返回与 self 对应的整数,该整数对于当前进程是唯一的。

  • private_methods: 返回 self 中私有方法的符号名称数组。

  • protected_methods: 返回 self 中受保护方法的符号名称数组。

  • public_method: 返回 self 中给定公共方法的 Method 对象。

  • public_methods: 返回 self 中公共方法的符号名称数组。

  • respond_to?: 返回 self 是否响应给定方法。

  • singleton_class: 返回 self 的单例类。

  • singleton_method: 返回 self 中给定单例方法的 Method 对象。

  • singleton_methods: 返回 self 中单例方法的符号名称数组。

  • define_singleton_method: 为给定的符号方法名和块或 proc 在 self 中定义一个单例方法。

  • extend: 在 self 的单例类中包含给定的模块。

  • public_send: 使用给定的参数调用 self 中给定的公共方法。

  • send: 使用给定的参数调用 self 中给定的方法。

实例变量

其他

  • clone: 返回 self 的浅拷贝,包括单例类和冻结状态。

  • define_singleton_method: 为给定的符号方法名和块或 proc 在 self 中定义一个单例方法。

  • display: 将 self 打印到给定的 IO 流或 $stdout

  • dup: 返回 self 的浅拷贝,未冻结。

  • enum_for (别名为 to_enum): 使用给定的方法、参数和块,为 self 返回一个 Enumerator

  • extend: 在 self 的单例类中包含给定的模块。

  • freeze: 阻止对 self 的进一步修改。

  • hash: 返回 self 的整数哈希值。

  • inspect: 返回 self 的人类可读字符串表示。

  • itself: 返回 self

  • method_missing: 当在 self 上调用未定义的方法时,会调用 Method

  • public_send: 使用给定的参数调用 self 中给定的公共方法。

  • send: 使用给定的参数调用 self 中给定的方法。

  • to_s: 返回 self 的字符串表示。

常量

ARGF

ARGF 是一个流,专为处理作为命令行参数给出的文件或通过 STDIN 传入的文件的脚本使用。

有关更多详细信息,请参阅 ARGF(类)。

ARGV

ARGV 包含用于运行 ruby 的命令行参数。

可以使用像 OptionParser 这样的库来处理命令行参数。

DATA

DATA 是一个 File,包含执行文件的 data 部分。要创建 data 部分,请使用 __END__

$ cat t.rb
puts DATA.gets
__END__
hello world!

$ ruby t.rb
hello world!
ENV

ENV 是一个类似 Hash 的访问器,用于访问环境变量。

有关更多详细信息,请参阅 ENV(类)。

ruby 的版权字符串

RUBY_DESCRIPTION

完整的 ruby 版本字符串,例如 ruby -v 打印

RUBY_ENGINE

此 ruby 使用的引擎或解释器。

RUBY_ENGINE_VERSION

此 ruby 使用的引擎或解释器的版本。

RUBY_PATCHLEVEL

此 ruby 的补丁级别。如果这是 ruby 的开发版本,则补丁级别将为 -1

RUBY_PLATFORM

此 ruby 的平台

RUBY_RELEASE_DATE

此 ruby 发布的日期

RUBY_REVISION

此 ruby 的 GIT 提交哈希。

RUBY_VERSION

正在运行的 ruby 版本

STDERR

保存原始 stderr

STDIN

保存原始 stdin

STDOUT

保存原始 stdout

TOPLEVEL_BINDING

顶层作用域的 Binding

公共实例方法

obj !~ other → true 或 false 点击以切换源代码

如果两个对象不匹配(使用 =~ 方法),则返回 true,否则返回 false。

static VALUE
rb_obj_not_match(VALUE obj1, VALUE obj2)
{
    VALUE result = rb_funcall(obj1, id_match, 1, obj2);
    return rb_obj_not(result);
}
obj <=> other → 0 或 nil 点击以切换源代码

如果 objother 是同一个对象或 obj == other,则返回 0,否则返回 nil。

#<=> 用于各种方法比较对象,例如 Enumerable#sortEnumerable#max 等。

您对 #<=> 的实现应返回以下值之一:-1、0、1 或 nil。-1 表示 self 小于 other。0 表示 self 等于 other。1 表示 self 大于 other。Nil 表示这两个值无法比较。

当您定义 #<=> 时,您可以包含 Comparable 以获得方法 #<=、#<、==、#>=、#> 和 between?。

static VALUE
rb_obj_cmp(VALUE obj1, VALUE obj2)
{
    if (rb_equal(obj1, obj2))
        return INT2FIX(0);
    return Qnil;
}
true === other → true 或 false 点击以切换源代码
false === other → true 或 false
nil === other → true 或 false

返回 truefalse

Object#== 相似,如果 objectObject 的实例(而不是其众多子类的实例)。

此方法通常被这些子类覆盖,以便在 case 语句中提供有意义的语义。

#define case_equal rb_equal
define_singleton_method(symbol, method) → symbol 点击切换源代码
define_singleton_method(symbol) { block } → symbol

在接收者中定义一个公共单例方法。method 参数可以是 ProcMethodUnboundMethod 对象。如果指定了块,则将其用作方法体。如果块或方法具有参数,则将其用作方法参数。

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!"
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);
}
display(port = $>) → nil 点击切换源代码

在给定端口上写入 self

1.display
"cat".display
[ 4, 5, 6 ].display
puts

输出

1cat[4, 5, 6]
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;
}
dup → an_object 点击切换源代码

生成 obj 的浅拷贝 - obj 的实例变量被复制,但它们引用的对象没有被复制。

此方法可能具有特定于类的行为。如果是这样,该行为将在类的 #initialize_copy 方法下进行记录。

关于 dup 与 clone

一般来说,clonedup 在子类中可能具有不同的语义。虽然 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>
VALUE
rb_obj_dup(VALUE obj)
{
    VALUE dup;

    if (special_object_p(obj)) {
        return obj;
    }
    dup = rb_obj_alloc(rb_obj_class(obj));
    init_copy(dup, obj);
    rb_funcall(dup, id_init_dup, 1, obj);

    return dup;
}
enum_for(method = :each, *args) → enum
enum_for(method = :each, *args){|*args| block} → enum

创建一个新的 Enumerator,它将通过在 obj 上调用 method 来枚举,如果存在,则传递 args。方法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
to_enum 的别名
obj == other → true 或 false 点击以切换源代码
equal?(other) → true 或 false
eql?(other) → true 或 false

相等性 - 在 Object 级别,== 仅当 objother 是同一个对象时才返回 true。通常,此方法在子类中被重写以提供特定于类的含义。

== 不同,equal? 方法不应被子类重写,因为它用于确定对象标识(即,a.equal?(b) 当且仅当 ab 是同一个对象时)。

obj = "a"
other = obj.dup

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

eql? 方法如果 objother 指向同一个哈希键,则返回 true。这由 Hash 用于测试成员的相等性。对于任何一对 eql? 返回 true 的对象,这两个对象的 hash 值必须相等。因此,任何重写 eql? 的子类也应该相应地重写 hash

对于类 Object 的对象,eql? 等同于 ==。子类通常通过将 eql? 设为其重写的 == 方法的别名来延续这一传统,但也有一些例外。例如,Numeric 类型在 == 中执行类型转换,但在 eql? 中不执行类型转换,因此

1 == 1.0     #=> true
1.eql? 1.0   #=> false
VALUE
rb_obj_equal(VALUE obj1, VALUE obj2)
{
    return RBOOL(obj1 == obj2);
}
extend(module, ...) → 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"
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;
}
freeze → 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

以下类的对象始终被冻结:IntegerFloatSymbol

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;
}
hash → integer 点击切换源代码

为该对象生成一个 Integer 哈希值。此函数必须具有以下属性:a.eql?(b) 意味着 a.hash == b.hash

哈希值与 eql? 一起由 Hash 类使用,以确定两个对象是否引用相同的哈希键。任何超过 Integer 容量的哈希值将在使用前被截断。

对象的哈希值可能在 Ruby 的不同调用或实现中不相同。如果您需要跨 Ruby 调用和实现的稳定标识符,则需要使用自定义方法生成一个。

某些核心类,例如 Integer,使用内置的哈希计算,并且在用作哈希键时不会调用 hash 方法。

在基于多个值实现自己的 hash 时,最佳做法是使用数组的哈希码组合类和任何值。

例如

def hash
  [self.class, a, b, c].hash
end

这样做的原因是 Array#hash 方法已经具有安全有效地组合多个哈希值的逻辑。

VALUE
rb_obj_hash(VALUE obj)
{
    long hnum = any_hash(obj, objid_hash);
    return ST2FIX(hnum);
}
inspect → string 点击切换源代码

返回一个字符串,其中包含 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>"
static VALUE
rb_obj_inspect(VALUE obj)
{
    if (rb_ivar_count(obj) > 0) {
        VALUE str;
        VALUE c = rb_class_name(CLASS_OF(obj));

        str = rb_sprintf("-<%"PRIsVALUE":%p", c, (void*)obj);
        return rb_exec_recursive(inspect_obj, obj, str);
    }
    else {
        return rb_any_to_s(obj);
    }
}
instance_of?(class) → true 或 false 点击切换源代码

如果 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
VALUE
rb_obj_is_instance_of(VALUE obj, VALUE c)
{
    c = class_or_module_required(c);
    return RBOOL(rb_obj_class(obj) == c);
}
instance_variable_defined?(symbol) → true 或 false 点击切换源代码
instance_variable_defined?(string) → true 或 false

如果给定的实例变量在 obj 中定义,则返回 trueString 参数将转换为符号。

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
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);
}
instance_variable_get(symbol) → obj 点击切换源代码
instance_variable_get(string) → obj

返回给定实例变量的值,如果实例变量未设置,则返回 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
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);
}
instance_variable_set(symbol, obj) → obj 点击切换源代码
instance_variable_set(string, obj) → obj

将名为 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\">"
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);
}
instance_variables → array click to toggle source

返回接收者的实例变量名称数组。请注意,仅仅定义访问器不会创建相应的实例变量。

class Fred
  attr_accessor :a1
  def initialize
    @iv = 3
  end
end
Fred.new.instance_variables   #=> [:@iv]
VALUE
rb_obj_instance_variables(VALUE obj)
{
    VALUE ary;

    ary = rb_ary_new();
    rb_ivar_foreach(obj, ivar_i, ary);
    return ary;
}
is_a?(class) → true 或 false

如果 classobj 的类,或者 classobj 的超类之一或包含在 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
别名:kind_of?
itself → obj click to toggle source

返回接收者。

string = "my string"
string.itself.object_id == string.object_id   #=> true
static VALUE
rb_obj_itself(VALUE obj)
{
    return obj;
}
kind_of?(class) → true 或 false click to toggle source

如果 classobj 的类,或者 classobj 的超类之一或包含在 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
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);
    }
}
也称为:is_a?
method(sym) → method click to toggle source

obj 中查找名为方法的方法作为接收者,返回一个 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)>]
VALUE
rb_obj_method(VALUE obj, VALUE vid)
{
    return obj_method(obj, vid, FALSE);
}
methods(regular=true) → array click to toggle source

返回 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]
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);
}
nil? → true 或 false click to toggle source

只有对象 nilnil? 响应 true

Object.new.nil?   #=> false
nil.nil?          #=> true
VALUE
rb_false(VALUE obj)
{
    return Qfalse;
}
__id__ → integer click to toggle source
object_id → integer

返回 obj 的整数标识符。

对于给定的对象,所有对 object_id 的调用都将返回相同的数字,并且没有两个活动对象会共享同一个 ID。

注意:为了优化,某些内置类对象会被重复使用。这种情况适用于立即值和冻结字符串字面量。

BasicObject 实现 +__id__+,Kernel 实现 object_id

立即值不是通过引用传递,而是通过值传递:niltruefalse、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
VALUE
rb_obj_id(VALUE obj)
{
    /*
     *                32-bit VALUE space
     *          MSB ------------------------ LSB
     *  false   00000000000000000000000000000000
     *  true    00000000000000000000000000000010
     *  nil     00000000000000000000000000000100
     *  undef   00000000000000000000000000000110
     *  symbol  ssssssssssssssssssssssss00001110
     *  object  oooooooooooooooooooooooooooooo00        = 0 (mod sizeof(RVALUE))
     *  fixnum  fffffffffffffffffffffffffffffff1
     *
     *                    object_id space
     *                                       LSB
     *  false   00000000000000000000000000000000
     *  true    00000000000000000000000000000010
     *  nil     00000000000000000000000000000100
     *  undef   00000000000000000000000000000110
     *  symbol   000SSSSSSSSSSSSSSSSSSSSSSSSSSS0        S...S % A = 4 (S...S = s...s * A + 4)
     *  object   oooooooooooooooooooooooooooooo0        o...o % A = 0
     *  fixnum  fffffffffffffffffffffffffffffff1        bignum if required
     *
     *  where A = sizeof(RVALUE)/4
     *
     *  sizeof(RVALUE) is
     *  20 if 32-bit, double is 4-byte aligned
     *  24 if 32-bit, double is 8-byte aligned
     *  40 if 64-bit
     */

    return rb_find_object_id(obj, cached_object_id);
}
private_methods(all=true) → array click to toggle source

返回 obj 可访问的私有方法列表。如果 all 参数设置为 false,则只列出接收器中的方法。

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);
}
protected_methods(all=true) → array click to toggle source

返回 obj 可访问的受保护方法列表。如果 all 参数设置为 false,则只列出接收器中的方法。

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);
}
public_method(sym) → method click to toggle source

类似于 method,只搜索公有方法。

VALUE
rb_obj_public_method(VALUE obj, VALUE vid)
{
    return obj_method(obj, vid, TRUE);
}
public_methods(all=true) → array click to toggle source

返回 obj 可访问的公有方法列表。如果 all 参数设置为 false,则只列出接收器中的方法。

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);
}
public_send(symbol [, args...]) → obj click to toggle source
public_send(string [, args...]) → obj

调用由 symbol 标识的方法,并传递任何指定的参数。与 send 不同,public_send 只调用公有方法。当方法由字符串标识时,字符串将被转换为符号。

1.public_send(:puts, "hello")  # causes NoMethodError
static VALUE
rb_f_public_send(int argc, VALUE *argv, VALUE recv)
{
    return send_internal_kw(argc, argv, recv, CALL_PUBLIC);
}
remove_instance_variable(symbol) → obj click to toggle source
remove_instance_variable(string) → obj

obj 中删除命名的实例变量,并返回该变量的值。String 参数将被转换为符号。

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
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 (val != Qundef) return val;
    }

    rb_name_err_raise("instance variable %1$s not defined",
                      obj, name);
    UNREACHABLE_RETURN(Qnil);
}
respond_to?(symbol, include_all=false) → true or false click to toggle source
respond_to?(string, include_all=false) → true or false

如果 obj 响应给定方法,则返回 true。只有当可选的第二个参数计算结果为 true 时,私有和受保护的方法才会包含在搜索中。

如果方法未实现,例如 Windows 上的 Process.fork、GNU/Linux 上的 File.lchmod 等,则返回 false。

如果方法未定义,则调用 respond_to_missing? 方法并返回结果。

当方法名参数以字符串形式给出时,该字符串将被转换为符号。

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)));
}
respond_to_missing?(symbol, include_all) → true 或 false 点击切换源代码
respond_to_missing?(string, include_all) → true 或 false

不要直接使用此方法。

钩子方法,用于返回obj是否可以响应id方法。

当方法名参数以字符串形式给出时,该字符串将被转换为符号。

参见 respond_to?,以及 BasicObject 的示例。

static VALUE
obj_respond_to_missing(VALUE obj, VALUE mid, VALUE priv)
{
    return Qfalse;
}
send(symbol [, args...]) → obj 点击切换源代码
__send__(symbol [, args...]) → obj
send(string [, args...]) → obj
__send__(string [, args...]) → obj

调用由symbol标识的方法,并将指定的所有参数传递给它。当方法由字符串标识时,该字符串将被转换为符号。

BasicObject 实现 +__send__+,Kernel 实现 send。当obj具有与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"
VALUE
rb_f_send(int argc, VALUE *argv, VALUE recv)
{
    return send_internal_kw(argc, argv, recv, CALL_FCALL);
}
singleton_class → class 点击切换源代码

返回obj的单例类。如果obj没有单例类,此方法将创建一个新的单例类。

如果objniltruefalse,它将分别返回 NilClassTrueClassFalseClass。如果objIntegerFloatSymbol,它将引发 TypeError

Object.new.singleton_class  #=> #<Class:#<Object:0xb7ce1e24>>
String.singleton_class      #=> #<Class:String>
nil.singleton_class         #=> NilClass
static VALUE
rb_obj_singleton_class(VALUE obj)
{
    return rb_singleton_class(obj);
}
singleton_method(sym) → method 点击切换源代码

类似于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
VALUE
rb_obj_singleton_method(VALUE obj, VALUE vid)
{
    VALUE klass = rb_singleton_class_get(obj);
    ID id = rb_check_id(&vid);

    if (NIL_P(klass) ||
        NIL_P(klass = RCLASS_ORIGIN(klass)) ||
        !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 {
        const rb_method_entry_t *me = rb_method_entry_at(klass, id);
        vid = ID2SYM(id);

        if (UNDEFINED_METHOD_ENTRY_P(me)) {
            /* goto undef; */
        }
        else if (UNDEFINED_REFINED_METHOD_P(me->def)) {
            /* goto undef; */
        }
        else {
            return mnew_from_me(me, klass, klass, obj, id, rb_cMethod, FALSE);
        }
    }

  /* undef: */
    rb_name_err_raise("undefined singleton method `%1$s' for `%2$s'",
                      obj, vid);
    UNREACHABLE_RETURN(Qundef);
}
singleton_methods(all=true) → array 点击切换源代码

返回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]
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 (RB_TYPE_P(obj, T_CLASS) && FL_TEST(obj, FL_SINGLETON)) {
        rb_singleton_class(obj);
    }
    klass = CLASS_OF(obj);
    origin = RCLASS_ORIGIN(klass);
    me_arg.list = st_init_numtable();
    me_arg.recur = recur;
    if (klass && FL_TEST(klass, FL_SINGLETON)) {
        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 && (FL_TEST(klass, FL_SINGLETON) || 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;
}
to_enum(method = :each, *args) → enum 点击切换源代码
to_enum(method = :each, *args) {|*args| block} → enum

创建一个新的 Enumerator,它将通过在 obj 上调用 method 来枚举,如果存在,则传递 args。方法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
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;
}
别名:enum_for
to_s → string 点击切换源代码

返回表示obj的字符串。默认的to_s 打印对象的类和对象 ID 的编码。作为特殊情况,作为 Ruby 程序初始执行上下文的顶级对象返回“main”。

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