Spec-Zone.ru › Ruby 4.0

класс 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.

Открытые методы экземпляра

!obj → true or false Показать исходный код
VALUE
rb_obj_not(VALUE obj)
{
    return RBOOL(!RTEST(obj));
}

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

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

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

1 == 1.0     #=> true
1.eql? 1.0   #=> false
Также имеет псевдоним: equal?
__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, object_id);
}

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

При каждом вызове object_id для данного объекта будет возвращаться одно и то же число, и ни у каких двух существующих объектов не будет одинакового идентификатора.

Примечание: некоторые объекты встроенных классов повторно используются для оптимизации. Это относится к непосредственным значениям и замороженным строковым литералам.

BasicObject реализует __id__, а Kernel реализует object_id.

Непосредственные значения передаются не по ссылке, а по значению: nil, true, false, 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
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);
}

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

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

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, предоставляя коду доступ к переменным экземпляра 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–2025 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.

Spec-Zone.ru

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