Spec-Zone.ru › Ruby 3.4

класс BasicObject

BasicObject является родительским классом для всех классов в Ruby. В частности, BasicObject — родительский класс класса Object, который сам по себе является по умолчанию родительским классом каждого класса Ruby:

class Foo; end
Foo.superclass    # => Object
Object.superclass # => BasicObject

BasicObject — единственный класс, у которого нет родителя:

BasicObject.superclass # => nil

Класс BasicObject может использоваться для создания иерархии объектов (например, класс Delegator), которая независима от иерархии объектов Ruby. Такие объекты:

  • Не имеют «загрязнения» пространства имён от множества методов, предоставляемых классом Object и его включённым модулем Kernel.

  • Не имеют определений общих классов, поэтому ссылки на такие общие классы должны быть полностью квалифицированными (::String, а не String).

Разнообразные стратегии могут быть использованы для предоставления полезных частей Стандартной Библиотеки в подклассах класса BasicObject:

  • Непосредственный подкласс может include Kernel, что определит методы, такие как puts, exit, и т.д.

  • Можно создать и включить пользовательский модуль, подобный Kernel.

  • Делегирование может быть использовано через method_missing:

    class MyObjectSystem < BasicObject
      DELEGATE = [:puts, :p]
    
      def method_missing(name, *args, &block)
        return super unless DELEGATE.include? name
        ::Kernel.send(name, *args, &block)
      end
    
      def respond_to_missing?(name, include_private = false)
        DELEGATE.include?(name)
      end
    end
    

Что здесь

Вот методы, определённые для BasicObject:

  • ::new: Возвращает новый экземпляр BasicObject.

  • !: Возвращает логическое отрицание self: true или false.

  • !=: Возвращает, равны ли self и заданный объект не равны.

  • ==: Возвращает, эквивалентны ли self и заданный объект.

  • __id__: Возвращает целочисленное идентификатор объекта для self.

  • __send__: Вызывает метод, идентифицированный заданным символом.

  • equal?: Возвращает, являются ли self и заданный объект одним и тем же объектом.

  • instance_eval: Оценивает заданную строку или блок в контексте self.

  • instance_exec: Выполняет заданный блок в контексте self, передавая заданные аргументы.

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

  • singleton_method_added: Вызывается, когда к self добавляется одиночный метод.

  • singleton_method_removed: Вызывается, когда одиночный метод удаляется из self.

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

Публичные методы класса

new
Исходный код
#define rb_obj_initialize rb_obj_dummy0

Возвращает новый BasicObject.

END_OF_DOCUMENT_MARKER

Методы публичного экземпляра

!obj → true или false
Исходный код
VALUE
rb_obj_not(VALUE obj)
{
    return RBOOL(!RTEST(obj));
}

Логическое отрицание.

obj != other → true или false
Исходный код
VALUE
rb_obj_not_equal(VALUE obj1, VALUE obj2)
{
    VALUE result = rb_funcall(obj1, id_eq, 1, obj2);
    return rb_obj_not(result);
}

Возвращает true, если два объекта не равны, иначе false.

obj == other → true или false
eql?(other) → true или 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, значения хэша для обоих объектов должны быть равны. Поэтому любой подкласс, который переопределяет eql?, должен соответствующим образом переопределить hash.

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

1 == 1.0     #=> true
1.eql? 1.0   #=> false
Также алиас: equal?
__id__ → целое
object_id → целое
Исходный код
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
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"
equal?(other) → true или false
eql?(other) → true или false

Равенство — На уровне 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, значения хэша для обоих объектов должны быть равны. Поэтому любой подкласс, который переопределяет eql?, должен соответствующим образом переопределить hash.

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

1 == 1.0     #=> true
1.eql? 1.0   #=> false
Алиас для: ==
instance_eval(string [, filename [, lineno]] ) → obj
instance_eval {|obj| block } → obj
Исходный код
static VALUE
rb_obj_instance_eval_internal(int argc, const VALUE *argv, VALUE self)
{
    return specific_eval(argc, argv, self, TRUE, RB_PASS_CALLED_KEYWORDS);
}

Вычисляет строку, содержащую Ruby-код, или заданный блок, в контексте получателя (obj). Для установки контекста переменная self устанавливается в obj во время выполнения кода, предоставляя коду доступ к переменным экземпляра и закрытым методам obj.

Когда instance_eval получает блок, obj также передаётся как единственный аргумент блока.

Когда instance_eval получает строку, необязательные второй и третий параметры предоставляют имя файла и номер начальной строки, используемые при сообщении об ошибках компиляции.

class KlassWithSecret
  def initialize
    @secret = 99
  end
  private
  def the_secret
    "Ssssh! The secret is #{@secret}."
  end
end
k = KlassWithSecret.new
k.instance_eval { @secret }          #=> 99
k.instance_eval { the_secret }       #=> "Ssssh! The secret is 99."
k.instance_eval {|obj| obj == self } #=> true
instance_exec(arg...) {|var...| block } → obj
Исходный код
static VALUE
rb_obj_instance_exec_internal(int argc, const VALUE *argv, VALUE self)
{
    return yield_under(self, TRUE, argc, argv, RB_PASS_CALLED_KEYWORDS);
}

Выполняет заданный блок в контексте получателя (obj). Для установки контекста переменная self устанавливается в obj во время выполнения кода, предоставляя коду доступ к переменным экземпляра. Аргументы передаются как параметры блока.

class KlassWithSecret
  def initialize
    @secret = 99
  end
end
k = KlassWithSecret.new
k.instance_exec(5) {|x| @secret+x }   #=> 104

Методы частного экземпляра

method_missing(symbol [, *args] ) → result
Исходный код
static VALUE
rb_method_missing(int argc, const VALUE *argv, VALUE obj)
{
    rb_execution_context_t *ec = GET_EC();
    raise_method_missing(ec, argc, argv, obj, ec->method_missing_reason);
    UNREACHABLE_RETURN(Qnil);
}

Вызывается Ruby, когда obj получает сообщение, которое он не может обработать. symbol — это символ вызываемого метода, а args — любые аргументы, которые были ему переданы. По умолчанию интерпретатор генерирует ошибку при вызове этого метода. Однако можно переопределить метод, чтобы обеспечить более динамичное поведение. Если решено, что определённый метод не должен обрабатываться, то необходимо вызвать super, чтобы предки могли обработать отсутствующий метод. В примере ниже создаётся класс Roman, который отвечает на методы с именами, состоящими из римских цифр, возвращая соответствующие целочисленные значения.

class Roman
  def roman_to_int(str)
    # ...
  end

  def method_missing(symbol, *args)
    str = symbol.id2name
    begin
      roman_to_int(str)
    rescue
      super(symbol, *args)
    end
  end
end

r = Roman.new
r.iv      #=> 4
r.xxiii   #=> 23
r.mm      #=> 2000
r.foo     #=> NoMethodError
singleton_method_added(symbol)
Исходный код
#define rb_obj_singleton_method_added rb_obj_dummy1

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

module Chatty
  def Chatty.singleton_method_added(id)
    puts "Adding #{id.id2name}"
  end
  def self.one()     end
  def two()          end
  def Chatty.three() end
end

выводит:

Adding singleton_method_added
Adding one
Adding three
singleton_method_removed(symbol)
Исходный код
#define rb_obj_singleton_method_removed rb_obj_dummy1

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

module Chatty
  def Chatty.singleton_method_removed(id)
    puts "Removing #{id.id2name}"
  end
  def self.one()     end
  def two()          end
  def Chatty.three() end
  class << self
    remove_method :three
    remove_method :one
  end
end

выводит:

Removing three
Removing one
singleton_method_undefined(symbol)
Исходный код
#define rb_obj_singleton_method_undefined rb_obj_dummy1

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

module Chatty
  def Chatty.singleton_method_undefined(id)
    puts "Undefining #{id.id2name}"
  end
  def Chatty.one()   end
  class << self
     undef_method(:one)
  end
end

выводит:

Undefining one

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