類別 Object

Object 是所有 Ruby 物件的預設根。 Object 繼承自 BasicObject,允許建立其他物件階層。 Object 上的方法可供所有類別使用,除非明確覆寫。

Object 會混入 Kernel 模組,讓內建核心函式可在全域使用。儘管 Object 的執行個體方法是由 Kernel 模組定義的,但我們選擇在這裡記錄它們以求清楚。

在參考繼承自 Object 的類別中的常數時,您不需要使用完整的命名空間。例如,在 YourClass 中參考 File 將會找到頂層 File 類別。

在 Object 方法的說明中,參數 符號 指的是符號,它可以是引號包住的字串或 Symbol(例如 :name)。

此處內容

首先,其他地方。類別物件

在此,類別物件提供以下方法

查詢

執行個體變數

其他

常數

ARGF

ARGF 是專門用於處理以命令列引數提供或透過 STDIN 傳遞的檔案的腳本中使用的串流。

詳細資訊請參閱 ARGF(類別)。

ARGV

ARGV 包含用於執行 Ruby 的命令列引數。

可以使用類似 OptionParser 的函式庫來處理命令列引數。

CROSS_COMPILING
DATA

DATA 是包含已執行檔案資料區段的 File。若要建立資料區段,請使用 __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 版本

Readline
RubyLex
STDERR

保留原始 stderr

STDIN

保留原始 stdin

STDOUT

保留原始 stdout

TOPLEVEL_BINDING

Binding 的頂層範圍

WIN32OLE_EVENT
WIN32OLE_METHOD
WIN32OLE_PARAM
WIN32OLE_RECORD
WIN32OLE_TYPE
WIN32OLE_TYPELIB
WIN32OLE_VARIABLE
WIN32OLE_VARIANT

公共類別方法

yaml_tag(url) 按一下以切換來源
# File ext/psych/lib/psych/core_ext.rb, line 3
def self.yaml_tag url
  Psych.add_tag(url, self)
end

公共執行個體方法

obj !~ other → true or 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 or 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
CSV(*args, **options, &block) 按一下以切換來源

args 傳遞給 CSV::instance

CSV("CSV,data").read
  #=> [["CSV", "data"]]

如果給定區塊,則會將執行個體傳遞給區塊,且傳回值會變成區塊的傳回值。

CSV("CSV,data") { |c|
  c.read.any? { |a| a.include?("data") }
} #=> true

CSV("CSV,data") { |c|
  c.read.any? { |a| a.include?("zombies") }
} #=> false

也可以給予 CSV 選項。

io = StringIO.new
CSV(io, col_sep: ";") { |csv| csv << ["a", "b", "c"] }

此 API 不適用於 Ractor。

# File lib/csv.rb, line 2876
def CSV(*args, **options, &block)
  CSV.instance(*args, **options, &block)
end
DelegateClass(superclass, &block) 按一下以切換來源

此函式庫的主要介面。在定義類別時使用來設定委派。

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 物件,對儲存位置和 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
呼叫超類別方法
# File lib/delegate.rb, line 394
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
  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
    protected_instance_methods.each do |method|
      define_method(method, Delegator.delegating_block(method))
      protected method
    end
    public_instance_methods.each do |method|
      define_method(method, Delegator.delegating_block(method))
    end
  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
Digest(name) → digest_subclass 按一下以切換來源

以執行緒安全的方式傳回 Digest 子類別,即使涉及依需求載入時也是如此。

require 'digest'

Digest("MD5")
# => Digest::MD5

Digest(:SHA256)
# => Digest::SHA256

Digest(:Foo)
# => LoadError: library not found for class Digest::Foo -- digest/foo
# 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
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));
    return rb_obj_dup_setup(obj, dup);
}
enum_for(method = :each, *args) → enum
enum_for(method = :each, *args){|*args| block} → enum

建立一個新的 Enumerator,它會透過在 obj 上呼叫 method 來列舉,如果有的話,會傳遞 args。method 產生的內容會變成列舉器的值。

如果給定區塊,它將用於計算列舉器的尺寸,而不需要反覆運算(請參閱 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) 當且僅當 a 是與 b 相同的物件時為真)

obj = "a"
other = obj.dup

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

如果 objother 參照相同的雜湊金鑰,eql? 方法會傳回 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 hash 值。此函數必須具有 a.eql?(b) 暗示 a.hash == b.hash 的屬性。

Hash 類別會使用 hash 值與 eql? 來判斷兩個物件是否參照相同的 hash 鍵。任何超過 Integer 容量的 hash 值在使用前都會被截斷。

物件的 hash 值在不同的 Ruby 呼叫或實作中可能不相同。如果您需要在不同的 Ruby 呼叫和實作中使用穩定的識別碼,則需要使用自訂方法產生一個識別碼。

某些核心類別(例如 Integer)會使用內建的 hash 計算,並且在用作 hash 鍵時不會呼叫 hash 方法。

在根據多個值實作您自己的 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 按一下以切換原始碼

傳回接收者的實例變數名稱陣列。請注意,僅定義存取器並不會建立對應的實例變數。

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 按一下以切換原始碼

傳回接收者。

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 按一下以切換原始碼

如果 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 按一下以切換原始碼

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 按一下以切換原始碼

傳回 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 按一下以切換原始碼

只有物件 nil 會對 nil? 回應 true

Object.new.nil?   #=> false
nil.nil?          #=> true
VALUE
rb_false(VALUE obj)
{
    return Qfalse;
}
__id__ → integer 按一下以切換原始碼
object_id → integer

傳回 obj 的整數識別碼。

對於特定物件,所有呼叫 object_id 都會傳回相同的數字,而且沒有兩個活動物件會共用一個識別碼。

請注意:內建類別的某些物件會重複使用以進行最佳化。立即值和凍結字串文字即為如此。

BasicObject 實作 __id__Kernel 實作 object_id

立即值不會以參照傳遞,而是以值傳遞:niltruefalse、Fixnum、符號和部分浮點數。

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 按一下以切換來源

傳回 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 按一下以切換來源

傳回 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 按一下以切換來源

類似於 method,只搜尋公開方法。

VALUE
rb_obj_public_method(VALUE obj, VALUE vid)
{
    return obj_method(obj, vid, TRUE);
}
public_methods(all=true) → array 按一下以切換來源

傳回 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 按一下以切換來源
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 按一下以切換來源
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 按一下以切換來源
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 or false 按一下以切換來源
respond_to_missing?(string, include_all) → true or 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。method 產生的內容會變成列舉器的值。

如果給定區塊,它將用於計算列舉器的尺寸,而不需要反覆運算(請參閱 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;
}
to_yaml(options = {}) 按一下以切換來源

將物件轉換為 YAML。有關可用的 options 的更多資訊,請參閱 Psych.dump

# File ext/psych/lib/psych/core_ext.rb, line 12
def to_yaml options = {}
  Psych.dump self, options
end
xmp(exps, bind = nil) 按一下以切換來源

只有在您需要 IRB::XMP 標準函式庫時才可用的便利方法。

建立新的 XMP 物件,使用指定的表達式作為 exps 參數,並將選用繫結作為 bind 或使用頂層繫結。然後使用 :XMP 提示模式評估指定的表達式。

例如

require 'irb/xmp'
ctx = binding
xmp 'foo = "bar"', ctx
#=> foo = "bar"
  #==>"bar"
ctx.eval 'foo'
#=> "bar"

有關更多資訊,請參閱 XMP.new

# File lib/irb/xmp.rb, line 159
def xmp(exps, bind = nil)
  bind = IRB::Frame.top(1) unless bind
  xmp = XMP.new(bind)
  xmp.puts exps
  xmp
end