Spec-Zone.ru › Ruby 3.4

класс Object

Родитель:
BasicObject
Включенные модули:
Kernel

Object является корневым объектом всех объектов Ruby. Object наследуется от BasicObject, что позволяет создавать альтернативные иерархии объектов. Методы класса Object доступны всем классам, если явно не переопределены.

Object включает в себя модуль Kernel, делая встроенные функции ядра глобально доступными. Хотя методы экземпляров Object определяются модулем Kernel, мы решили документировать их здесь для ясности.

При обращении к константам в классах, наследующих от Object, вам не нужно использовать полное имя пространства имён. Например, обращение к File внутри YourClass найдёт верхнеуровневый класс File.

В описаниях методов объекта Object параметр символ относится к символу, который является либо строкой в кавычках, либо Symbol (например, :name).

Что здесь

Сначала, что где-то еще. Класс Object:

  • Наследуется от класса BasicObject.

  • Включает модуль Kernel.

Здесь класс Object предоставляет методы для:

  • Запросов

  • Переменных экземпляра

  • Другого

Запросы

  • !~: Возвращает true если self не соответствует заданному объекту, в противном случае false.

  • <=>: Возвращает 0, если self и заданный объект object являются одним и тем же объектом, или если self == object, иначе возвращает nil.

  • ===: Реализует равенство по типу, фактически то же самое, что вызов ==.

  • eql?: Реализует равенство для хешей, фактически то же самое, что вызов ==.

  • kind_of? (алиас is_a?): Возвращает, является ли переданный аргумент предком единственного класса self.

  • instance_of?: Возвращает, является ли self экземпляром заданного класса.

  • instance_variable_defined?: Возвращает, определена ли заданная переменная экземпляра в self.

  • method: Возвращает объект Method для заданного метода в self.

  • methods: Возвращает массив имён символов общедоступных и защищённых методов в self.

  • nil?: Возвращает false. (Только nil отвечает true на метод nil?.)

  • object_id: Возвращает целое число, соответствующее self, уникальное для текущего процесса.

  • private_methods: Возвращает массив имён символов закрытых методов в self.

  • protected_methods: Возвращает массив имён символов защищённых методов в self.

  • public_method: Возвращает объект Method для данного публичного метода в self.

  • public_methods: Возвращает массив имён символов публичных методов в self.

  • respond_to?: Возвращает, отвечает ли self на данный метод.

  • singleton_class: Возвращает единственный класс self.

  • singleton_method: Возвращает объект Method для данного единственного метода в self.

  • singleton_methods: Возвращает массив имён символов единственных методов в self.

  • define_singleton_method: Определяет единственный метод в self для данного метода-символа и блока или прок.

  • 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 для данного символа метода и блока или прок.

  • display: Выводит self в заданный поток IO или $stdout.

  • dup: Возвращает поверхностную неотмороженную копию self.

  • enum_for (алиас to_enum): Возвращает Enumerator для self с использованием заданного метода, аргументов и блока.

  • extend: Включает заданные модули в единственный класс self.

  • freeze: Запрещает дальнейшие изменения в self.

  • hash: Возвращает целое числовое значение хеша для self.

  • inspect: Возвращает удобочитаемую строку представления для self.

  • itself: Возвращает self.

  • method_missing: Method вызывается, когда вызывается неопределённый метод для self.

  • public_send: Вызывает заданный публичный метод в self с заданным аргументом.

  • send: Вызывает заданный метод в self с заданным аргументом.

  • to_s: Возвращает строковое представление self.

Константы

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_COPYRIGHT

Строка авторских прав для 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

Хеш GIT коммита для этого ruby.

RUBY_VERSION

Запущенная версия ruby

Readline
Ripper

Это записывает перевод риппера prism в константу Ripper, чтобы пользователи могли прозрачно использовать Ripper без каких-либо изменений.

STDERR

Содержит исходный STDERR

STDIN

Содержит исходный STDIN

STDOUT

Содержит исходный STDOUT

TOPLEVEL_BINDING

Binding верхнего уровня области видимости

Методы открытого класса

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
Исходный код
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.

obj <=> other → 0 or nil
Исходный код
static VALUE
rb_obj_cmp(VALUE obj1, VALUE obj2)
{
    if (rb_equal(obj1, obj2))
        return INT2FIX(0);
    return Qnil;
}

Возвращает 0, если obj и other это один и тот же объект или obj == other, иначе nil.

Метод <=> используется различными методами для сравнения объектов, например Enumerable#sort, Enumerable#max и т.д.

Ваша реализация <=> должна возвращать одно из следующих значений: -1, 0, 1 или nil. -1 означает, что self меньше, чем other. 0 означает, что self равен other. 1 означает, что self больше, чем other. Nil означает, что два значения не могут быть сравнены.

При определении <=>, вы можете включить Comparable, чтобы получить методы <=, <, ==, >=, > и between?.

true === other → true or false
false === other → true or false
nil === other → true or false
Исходный код
#define case_equal rb_equal

Возвращает true или false.

Как и Object#==, если object является экземпляром Object (и не является экземпляром одного из его многих подклассов).

Этот метод обычно переопределяется этими подклассами, чтобы обеспечить осмысленную семантику в операторах case.

DelegateClass (superclass, &block)
Исходный код
# 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

Основной интерфейс этой библиотеки. Используйте для настройки делегирования при определении вашего класса.

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
Вызывает метод суперкласса
Digest(name) → digest_subclass
Исходный код
# 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

Возвращает подкласс Digest с помощью name потокобезопасным способом, даже когда используется загрузка по требованию.

require 'digest'

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

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

Digest(:Foo)
# => LoadError: library not found for class Digest::Foo -- digest/foo
define_singleton_method(symbol, method) → symbol
define_singleton_method(symbol) { block } → symbol
Исходный код
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!"
display(port = $>) → nil
Исходный код
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]
dup → an_object
Исходный код
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 класса.

on dup vs 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>
enum_for(method = :each, *args) → enum
enum_for(method = :each, *args){|*args| block} → enum

Создает новый Enumerator, который будет перечислять, вызывая method на obj, передавая args, если таковые имеются. То, что было выдано методом, становится значениями перечислителя.

Если задан блок, он будет использоваться для вычисления размера перечислителя без необходимости его итерации (см. 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

Типично вызывать to_enum при определении методов для обобщенного Enumerable, если блок не передан.

Вот такой пример с передачей параметров и блоком определения размера:

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 or false
equal?(other) → true or false
eql?(other) → true or false
Исходный код
VALUE
rb_obj_equal(VALUE obj1, VALUE obj2)
{
    return RBOOL(obj1 == obj2);
}

Равенство — На уровне Object, == возвращает true только если obj и other это один и тот же объект. Как правило, этот метод переопределяется в дочерних классах для обеспечения специфического для класса значения.

В отличие от ==, метод equal? никогда не должен переопределяться подклассами, поскольку он используется для определения идентичности объекта (то есть, a.equal?(b) если и только если a это тот же самый объект, что и b):

obj = "a"
other = obj.dup

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

Метод eql? возвращает true, если obj и other ссылаются на один и тот же ключ хэша. Это используется Hash для проверки элементов на равенство. Для любой пары объектов, где eql? возвращает true, значение hash обоих объектов должно быть равным. Таким образом, любой подкласс, который переопределяет eql?, должен также соответствующим образом переопределить hash.

Для объектов класса Object, eql? является синонимом ==. Подклассы обычно продолжают эту традицию, создавая псевдоним eql? для их переопределенного метода ==, но есть исключения. Типы Numeric, например, выполняют преобразование типов через ==, но не через eql?, поэтому:

1 == 1.0     #=> true
1.eql? 1.0   #=> false
extend(module, ...) → obj
Исходный код
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"
freeze → obj
Исходный код
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

Объекты следующих классов всегда заморожены: Integer, Float, Symbol.

hash → integer
Исходный код
VALUE
rb_obj_hash(VALUE obj)
{
    long hnum = any_hash(obj, objid_hash);
    return ST2FIX(hnum);
}

Генерирует целочисленное хэш-значение 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 уже имеет логику для безопасного и эффективного объединения нескольких хэш-значений.

inspect → string
Исходный код
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);
    }
}

Возвращает строку, содержащую читаемое человеком представление 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>"
instance_of?(class) → true or false
Исходный код
VALUE
rb_obj_is_instance_of(VALUE obj, VALUE c)
{
    c = class_or_module_required(c);
    return RBOOL(rb_obj_class(obj) == c);
}

Возвращает true, если obj является экземпляром данного класса. См. также 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
instance_variable_defined?(symbol) → true or false
instance_variable_defined?(string) → true or 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);
}

Возвращает true, если данная переменная экземпляра определена в obj. Аргументы 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
instance_variable_get(symbol) → obj
instance_variable_get(string) → obj
Исходный код
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
instance_variable_set(symbol, obj) → obj
instance_variable_set(string, obj) → obj
Исходный код
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\">"
instance_variables → array
Исходный код
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]
is_a?(class) → true or false

Возвращает true если class является классом obj, или если class является одним из суперклассов obj или модулей, включенных в obj.

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
Исходный код
static VALUE
rb_obj_itself(VALUE obj)
{
    return obj;
}

Возвращает получателя.

string = "my string"
string.itself.object_id == string.object_id   #=> true
kind_of?(class) → true or false
Исходный код
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);
    }
}

Возвращает true если class является классом obj, или если class является одним из суперклассов obj или модулей, включенных в obj.

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
Также является псевдонимом для: is_a?
method(sym) → method
Исходный код
VALUE
rb_obj_method(VALUE obj, VALUE vid)
{
    return obj_method(obj, vid, FALSE);
}

Ищет именованный метод как получатель в 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)>]
methods(regular=true) → array
Исходный код
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]
nil? → true or false
Исходный код
VALUE
rb_false(VALUE obj)
{
    return Qfalse;
}

Только объект nil отвечает true на nil?.

Object.new.nil?   #=> false
nil.nil?          #=> true
__id__ → integer
object_id → integer
Исходный код
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, rb_gc_impl_object_id);
}

Возвращает целочисленный идентификатор для obj.

Одно и то же число будет возвращено на всех вызовах object_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
private_methods(all=true) → array
Исходный код
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, будут перечислены только те методы, которые находятся в получателе.

protected_methods(all=true) → array
Исходный код
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, будут перечислены только те методы, которые находятся в получателе.

public_method(sym) → method
Исходный код
VALUE
rb_obj_public_method(VALUE obj, VALUE vid)
{
    return obj_method(obj, vid, TRUE);
}

Аналогично method, ищет только открытые методы.

public_methods(all=true) → array
Исходный код
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, будут перечислены только те методы, которые находятся в получателе.

public_send(symbol [, args...]) → obj
public_send(string [, args...]) → obj
Исходный код
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
remove_instance_variable(symbol) → obj
remove_instance_variable(string) → obj
Исходный код
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
respond_to?(symbol, include_all=false) → true или false
respond_to?(string, include_all=false) → true или false
Исходный код
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)));
}

Возвращает true , если obj реагирует на указанный метод. Приватные и защищённые методы включаются в поиск только если необязательный второй параметр имеет значение true.

Если метод не реализован, как Process.fork в Windows, File.lchmod в GNU/Linux и т.д., возвращается false.

Если метод не определен, вызывается метод respond_to_missing?, и возвращается его результат.

Если имя метода передаётся в виде строки, эта строка преобразуется в символ.

respond_to_missing?(symbol, include_all) → true или false
respond_to_missing?(string, include_all) → true или false
Исходный код
static VALUE
obj_respond_to_missing(VALUE obj, VALUE mid, VALUE priv)
{
    return Qfalse;
}

НЕ ИСПОЛЬЗОВАТЬ НЕПОСРЕДСТВЕННО.

Метод-обработчик, возвращающий, может ли obj реагировать на метод id или нет.

Если имя метода передаётся в виде строки, эта строка преобразуется в символ.

См. respond_to? и пример из BasicObject.

send(symbol [, args...]) → obj
__send__(symbol [, args...]) → obj
send(string [, args...]) → obj
__send__(string [, args...]) → obj
Исходный код
VALUE
rb_f_send(int argc, VALUE *argv, VALUE recv)
{
    return send_internal_kw(argc, argv, recv, CALL_FCALL);
}

Вызывает метод, идентифицируемый символом, передавая ему все указанные аргументы. Если метод идентифицируется строкой, строка преобразуется в символ.

BasicObject реализует __send__, Kernel реализует send. __send__ безопаснее, чем send , когда у obj есть одноимённый метод, как у Socket. См. также public_send.

class Klass
  def hello(*args)
    "Hello " + args.join(' ')
  end
end
k = Klass.new
k.send :hello, "gentle", "readers"   #=> "Hello gentle readers"
singleton_class → class
Исходный код
static VALUE
rb_obj_singleton_class(VALUE obj)
{
    return rb_singleton_class(obj);
}

Возвращает синглтон-класс obj. Этот метод создаёт новый синглтон-класс, если obj его не имеет.

Если obj — nil, true, или false, возвращает NilClass, TrueClass или FalseClass соответственно. Если obj — Integer, Float или Symbol, генерирует исключение TypeError.

Object.new.singleton_class  #=> #<Class:#<Object:0xb7ce1e24>>
String.singleton_class      #=> #<Class:String>
nil.singleton_class         #=> NilClass
singleton_method(sym) → method
Исходный код
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
singleton_methods(all=true) → массив
Исходный код
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]
to_enum(method = :each, *args) → перечисление
to_enum(method = :each, *args) {|*args| блок} → перечисление
Исходный код
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, которое будет перечислять, вызывая method на obj, передавая args при необходимости. То, что было передано методом, становится значениями перечисления.

Если задан блок, он будет использоваться для вычисления размера перечисления без необходимости его итерации (см. 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

Обычно используется to_enum при определении методов для универсального Enumerable, если не задан блок.

Вот такой пример с передачей параметров и блоком вычисления размера:

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
Также алиас: enum_for
to_s → строка
Исходный код
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 выводит класс объекта и кодировку идентификатора объекта. В качестве специального случая, главный объект, являющийся начальной средой выполнения программ Ruby, возвращает “main”.

to_yaml(options = {})
Исходный код
# File ext/psych/lib/psych/core_ext.rb, line 12
def to_yaml options = {}
  Psych.dump self, options
end

Преобразует объект в YAML. Для получения дополнительной информации о доступных options, см. Psych.dump.

Ruby Core © 1993–2024 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API