класс Object
Object является корневым объектом всех объектов Ruby. Object наследуется от BasicObject, что позволяет создавать альтернативные иерархии объектов. Методы Object доступны для всех классов, если они не переопределены.
Object включает в себя модуль Kernel, делая встроенные функции ядра доступными глобально. Хотя методы экземпляров Object определены модулем Kernel, мы решили задокументировать их здесь для ясности.
При ссылке на константы в классах, наследуемых от Object, вам не нужно использовать полное имя пространства имён. Например, ссылка на File внутри YourClass найдет класс верхнего уровня File.
В описаниях методов объекта параметр символ относится к символу, который может быть строкой в кавычках или Symbol (например, :name).
Константы
- ARGF
-
ARGF— поток, предназначенный для использования в скриптах, которые обрабатывают файлы, переданные в качестве аргументов командной строки или черезSTDIN.См.
ARGF(класс) для получения дополнительной информации. - ARGV
-
ARGVсодержит аргументы командной строки, используемые для запуска ruby.Для обработки аргументов командной строки можно использовать библиотеку, такую как
OptionParser. - AmbiguousTaskError
- Bignum
-
Устаревший класс, используйте
Integer - CROSS_COMPILING
- DATA
-
DATA—File, содержащий раздел данных исполняемого файла. Для создания раздела данных используйте__END__:$ cat t.rb puts DATA.gets __END__ hello world! $ ruby t.rb hello world!
- ENV
-
ENV— объект, похожий на Hash, для доступа к переменным окружения.См.
ENV(класс) для получения дополнительной информации. - FALSE
-
Устаревший псевдоним
false - Fixnum
-
Устаревший класс, используйте
Integer - NIL
-
Устаревший псевдоним
nil - ParseError
- 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
- STDERR
-
Содержит исходный stderr
- STDIN
-
Содержит исходный stdin
- STDOUT
-
Содержит исходный stdout
- TOPLEVEL_BINDING
-
Bindingверхнего уровня - TRUE
-
Устаревший псевдоним
true - TimeoutError
-
Выбрасывается методом
Timeout.timeout, когда блок превышает лимит времени. - UndefinedTaskError
-
Выбрасывается, когда команда не найдена.
Общедоступные методы класса
# File ext/psych/lib/psych/core_ext.rb, line 3 def self.yaml_tag url Psych.add_tag(url, self) end
Общедоступные методы экземпляров
static VALUE
rb_obj_not_match(VALUE obj1, VALUE obj2)
{
VALUE result = rb_funcall(obj1, id_match, 1, obj2);
return RTEST(result) ? Qfalse : Qtrue;
} Возвращает true, если два объекта не совпадают (используя метод =~), в противном случае — false.
static VALUE
rb_obj_cmp(VALUE obj1, VALUE obj2)
{
if (obj1 == obj2 || 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?.
VALUE
rb_equal(VALUE obj1, VALUE obj2)
{
VALUE result;
if (obj1 == obj2) return Qtrue;
result = rb_equal_opt(obj1, obj2);
if (result == Qundef) {
result = rb_funcall(obj1, id_eq, 1, obj2);
}
if (RTEST(result)) return Qtrue;
return Qfalse;
} Сравнение по типу — для класса Object фактически эквивалентно вызову #==, но обычно переопределяется потомками для обеспечения осмысленной семантики в операторах case.
static VALUE
rb_obj_match(VALUE obj1, VALUE obj2)
{
if (rb_warning_category_enabled_p(RB_WARN_CATEGORY_DEPRECATED)) {
rb_warn("deprecated Object#=~ is called on %"PRIsVALUE
"; it always returns nil", rb_obj_class(obj1));
}
return Qnil;
} Этот метод устарел.
Он не только бесполезен, но и проблематичен, так как может скрывать ошибку типа.
# File lib/csv.rb, line 1507 def CSV(*args, &block) CSV.instance(*args, &block) end
Передает 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
# File lib/delegate.rb, line 388
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.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
# File ext/digest/lib/digest.rb, line 96
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
VALUE
rb_obj_class(VALUE obj)
{
return rb_class_real(CLASS_OF(obj));
} Возвращает класс obj. Этот метод всегда должен вызываться с явным получателем, так как class также является зарезервированным словом в Ruby.
1.class #=> Integer self.class #=> Object
static VALUE
rb_obj_clone2(int argc, VALUE *argv, VALUE obj)
{
int kwfreeze = freeze_opt(argc, argv);
if (!special_object_p(obj))
return mutable_obj_clone(obj, kwfreeze);
return immutable_obj_clone(obj, kwfreeze);
} Создает поверхностную копию obj — переменные экземпляра obj копируются, но не объекты, на которые они ссылаются. clone копирует замороженное (если :freeze ключевой аргумент не задан со значением false) состояние obj. См. также обсуждение в Object#dup.
class Klass attr_accessor :str end s1 = Klass.new #=> #<Klass:0x401b3a38> s1.str = "Hello" #=> "Hello" s2 = s1.clone #=> #<Klass:0x401b3998 @str="Hello"> s2.str[1,4] = "i" #=> "i" s1.inspect #=> "#<Klass:0x401b3a38 @str=\"Hi\">" s2.inspect #=> "#<Klass:0x401b3998 @str=\"Hi\">"
Этот метод может иметь поведение, специфичное для класса. В таком случае это поведение будет документировано в методе #initialize_copy класса.
# File lib/rexml/xpath_parser.rb, line 13 def dclone clone end
предоставляет унифицированную clone операцию для REXML::XPathParser для использования с различными типами Object.
static VALUE
rb_obj_define_method(int argc, VALUE *argv, VALUE obj)
{
VALUE klass = rb_singleton_class(obj);
return rb_mod_define_method(argc, argv, klass);
} Определяет метод-экземпляр в получателе. Параметр 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!"
static VALUE
rb_obj_display(int argc, VALUE *argv, VALUE self)
{
VALUE out;
out = (!rb_check_arity(argc, 0, 1) ? rb_stdout : argv[0]);
rb_io_write(out, self);
return Qnil;
} Выводит obj в заданном порту (по умолчанию $>). Эквивалентно:
def display(port=$>) port.write self nil end
Например:
1.display "cat".display [ 4, 5, 6 ].display puts
дает вывод:
1cat[4, 5, 6]
VALUE
rb_obj_dup(VALUE obj)
{
VALUE dup;
if (special_object_p(obj)) {
return obj;
}
dup = rb_obj_alloc(rb_obj_class(obj));
init_copy(dup, obj);
rb_funcall(dup, id_init_dup, 1, obj);
return dup;
} Создаёт поверхностную копию obj — переменные экземпляра obj копируются, но не объекты, на которые они ссылаются.
Этот метод может иметь поведение, специфичное для класса. В таком случае это поведение будет документировано в методе #initialize_copy класса.
о dup и 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:0x401b3a38> s2.foo #=> "foo" s3 = s1.dup #=> #<Klass:0x401b3a38> s3.foo #=> NoMethodError: undefined method `foo' for #<Klass:0x401b3a38>
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()) {
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
MJIT_FUNC_EXPORTED VALUE
rb_obj_equal(VALUE obj1, VALUE obj2)
{
if (obj1 == obj2) return Qtrue;
return Qfalse;
} Равенство — На уровне 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
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);
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"
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. Будет возбуждено исключение RuntimeError, если будет предпринята попытка модификации. Нет возможности разморозить замороженный объект. См. также 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.
VALUE
rb_obj_frozen_p(VALUE obj)
{
return OBJ_FROZEN(obj) ? Qtrue : Qfalse;
} Возвращает статус заморозки obj.
a = [ "a", "b", "c" ] a.freeze #=> ["a", "b", "c"] a.frozen? #=> true
# File lib/bundler/inline.rb, line 32
def gemfile(install = false, options = {}, &gemfile)
require_relative "../bundler"
opts = options.dup
ui = opts.delete(:ui) { Bundler::UI::Shell.new }
ui.level = "silent" if opts.delete(:quiet)
raise ArgumentError, "Unknown options: #{opts.keys.join(", ")}" unless opts.empty?
begin
old_root = Bundler.method(:root)
bundler_module = class << Bundler; self; end
bundler_module.send(:remove_method, :root)
def Bundler.root
Bundler::SharedHelpers.pwd.expand_path
end
old_gemfile = ENV["BUNDLE_GEMFILE"]
Bundler::SharedHelpers.set_env "BUNDLE_GEMFILE", "Gemfile"
Bundler::Plugin.gemfile_install(&gemfile) if Bundler.feature_flag.plugins?
builder = Bundler::Dsl.new
builder.instance_eval(&gemfile)
Bundler.settings.temporary(:frozen => false) do
definition = builder.to_definition(nil, true)
def definition.lock(*); end
definition.validate_runtime!
Bundler.ui = install ? ui : Bundler::UI::Silent.new
if install || definition.missing_specs?
Bundler.settings.temporary(:inline => true, :disable_platform_warnings => true) do
installer = Bundler::Installer.install(Bundler.root, definition, :system => true)
installer.post_install_messages.each do |name, message|
Bundler.ui.info "Post-install message from #{name}:\n#{message}"
end
end
end
runtime = Bundler::Runtime.new(nil, definition)
runtime.setup.require
end
ensure
if bundler_module
bundler_module.send(:remove_method, :root)
bundler_module.send(:define_method, :root, old_root)
end
if old_gemfile
ENV["BUNDLE_GEMFILE"] = old_gemfile
else
ENV["BUNDLE_GEMFILE"] = ""
end
end
end Позволяет объявлять Gemfile внутри ruby скрипта, при необходимости устанавливая любые гемы, которые еще не установлены в системе пользователя.
@note Каждый гем, указанный в этом 'Gemfile', будет `require`d, как если бы
the user had manually called `Bundler.require`. To avoid a requested gem being automatically required, add the `:require => false` option to the `gem` dependency declaration.
@param install [Boolean] устанавливать ли гемы, которые еще не установлены в
user's system should be installed. Defaults to `false`.
@param gemfile [Proc] блок, который вычисляется как `Gemfile`.
@example Использование встроенного Gemfile
#!/usr/bin/env ruby require 'bundler/inline' gemfile do source 'https://rubygems.org' gem 'json', require: false gem 'nap', require: 'rest' gem 'cocoapods', '~> 0.34.1' end puts Pod::VERSION # => "0.34.4"
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, вам нужно будет сгенерировать его с помощью пользовательского метода.
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>"
VALUE
rb_obj_is_instance_of(VALUE obj, VALUE c)
{
c = class_or_module_required(c);
if (rb_obj_class(obj) == c) return Qtrue;
return Qfalse;
} Возвращает 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
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
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
static VALUE
rb_obj_ivar_set(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\">"
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]
VALUE
rb_obj_is_kind_of(VALUE obj, VALUE c)
{
VALUE cl = CLASS_OF(obj);
c = class_or_module_required(c);
return class_search_ancestor(cl, RCLASS_ORIGIN(c)) ? Qtrue : 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
static VALUE
rb_obj_itself(VALUE obj)
{
return obj;
} Возвращает получателя.
string = "my string" string.itself.object_id == string.object_id #=> true
VALUE
rb_obj_is_kind_of(VALUE obj, VALUE c)
{
VALUE cl = CLASS_OF(obj);
c = class_or_module_required(c);
return class_search_ancestor(cl, RCLASS_ORIGIN(c)) ? Qtrue : 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
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)>]
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]
# File lib/bundler/vendor/thor/lib/thor/rake_compat.rb, line 61
def namespace(name)
if klass = Bundler::Thor::RakeCompat.rake_classes.last # rubocop:disable AssignmentInCondition
const_name = Bundler::Thor::Util.camel_case(name.to_s).to_sym
klass.const_set(const_name, Class.new(Bundler::Thor))
new_klass = klass.const_get(const_name)
Bundler::Thor::RakeCompat.rake_classes << new_klass
end
super
Bundler::Thor::RakeCompat.rake_classes.pop
end MJIT_FUNC_EXPORTED VALUE
rb_false(VALUE obj)
{
return Qfalse;
} Только объект nil отвечает true на nil?.
Object.new.nil? #=> false nil.nil? #=> 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);
} Возвращает целочисленный идентификатор для 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
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, будут перечислены только те методы, которые находятся в получателе.
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, будут перечислены только те методы, которые находятся в получателе.
VALUE
rb_obj_public_method(VALUE obj, VALUE vid)
{
return obj_method(obj, vid, TRUE);
} Аналогично методу method, ищет только публичные методы.
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, будут перечислены только те методы, которые находятся в получателе.
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
VALUE
rb_obj_remove_instance_variable(VALUE obj, VALUE name)
{
VALUE val = Qnil;
const ID id = id_for_var(obj, name, an, instance);
st_data_t n, v;
struct st_table *iv_index_tbl;
st_data_t index;
rb_check_frozen(obj);
if (!id) {
goto not_defined;
}
switch (BUILTIN_TYPE(obj)) {
case T_OBJECT:
iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj);
if (!iv_index_tbl) break;
if (!st_lookup(iv_index_tbl, (st_data_t)id, &index)) break;
if (ROBJECT_NUMIV(obj) <= index) break;
val = ROBJECT_IVPTR(obj)[index];
if (val != Qundef) {
ROBJECT_IVPTR(obj)[index] = Qundef;
return val;
}
break;
case T_CLASS:
case T_MODULE:
n = id;
if (RCLASS_IV_TBL(obj) && st_delete(RCLASS_IV_TBL(obj), &n, &v)) {
return (VALUE)v;
}
break;
default:
if (FL_TEST(obj, FL_EXIVAR)) {
if (generic_ivar_remove(obj, id, &val)) {
return val;
}
}
break;
}
not_defined:
rb_name_err_raise("instance variable %1$s not defined",
obj, name);
UNREACHABLE_RETURN(Qnil);
} Удаляет именованную локальную переменную из 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
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 (ret == Qundef) ret = Qfalse;
return ret;
}
if (basic_obj_respond_to(ec, obj, id, !RTEST(priv)))
return Qtrue;
return Qfalse;
} Возвращает true, если obj отвечает на данный метод. Приватные и защищённые методы включаются в поиск только если необязательный второй параметр имеет значение true.
Если метод не реализован, например, Process.fork в Windows, File.lchmod в GNU/Linux и т. д., возвращается false.
Если метод не определён, вызывается метод respond_to_missing? и возвращается результат.
Если имя метода задано как строка, строка преобразуется в символ.
static VALUE
obj_respond_to_missing(VALUE obj, VALUE mid, VALUE priv)
{
return Qfalse;
} НЕ ИСПОЛЬЗУЙТЕ ЭТО НЕПОСРЕДСТВЕННО.
Метод-обработчик для проверки, может ли obj ответить на метод id.
См. respond_to? и пример из BasicObject.
VALUE
rb_f_send(int argc, VALUE *argv, VALUE recv)
{
return send_internal_kw(argc, argv, recv, CALL_FCALL);
} Вызывает метод, идентифицируемый символом symbol, передавая ему любые указанные аргументы. Вы можете использовать __send__, если имя send конфликтует с существующим методом в obj. Если метод идентифицируется строкой, строка преобразуется в символ.
BasicObject реализует +__send__+, Kernel реализует send.
class Klass
def hello(*args)
"Hello " + args.join(' ')
end
end
k = Klass.new
k.send :hello, "gentle", "readers" #=> "Hello gentle readers"
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
VALUE
rb_obj_singleton_method(VALUE obj, VALUE vid)
{
const rb_method_entry_t *me;
VALUE klass = rb_singleton_class_get(obj);
ID id = rb_check_id(&vid);
if (NIL_P(klass) || NIL_P(klass = RCLASS_ORIGIN(klass))) {
undef:
rb_name_err_raise("undefined singleton method `%1$s' for `%2$s'",
obj, vid);
}
if (!id) {
VALUE m = mnew_missing_by_name(klass, obj, &vid, FALSE, rb_cMethod);
if (m) return m;
goto undef;
}
me = rb_method_entry_at(klass, id);
if (UNDEFINED_METHOD_ENTRY_P(me) ||
UNDEFINED_REFINED_METHOD_P(me->def)) {
vid = ID2SYM(id);
goto undef;
}
return mnew_from_me(me, klass, klass, obj, id, rb_cMethod, FALSE);
} Аналогично методу 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_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;
} Возвращает массив имён методов единственного класса для 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]
# File lib/webrick/httpservlet/cgi_runner.rb, line 12
def sysread(io, size)
buf = ""
while size > 0
tmp = io.sysread(size)
buf << tmp
size -= tmp.bytesize
end
return buf
end cgi_runner.rb – запуск CGI.
Автор: IPR – Программирование на Ruby в Интернете – авторы Авторские права © 2000 TAKAHASHI Masayoshi, GOTOU YUUZOU Авторские права © 2002 Авторы Руководства по программированию на Ruby в Интернете. Все права защищены.
$IPR: cgi_runner.rb,v 1.9 2002/09/25 11:33:15 gotoyuzo Exp $
VALUE
rb_obj_taint(VALUE obj)
{
rb_warning("Object#taint is deprecated and will be removed in Ruby 3.2.");
return obj;
} Возвращает объект. Этот метод устарел и будет удалён в Ruby 3.2.
VALUE
rb_obj_tainted(VALUE obj)
{
rb_warning("Object#tainted? is deprecated and will be removed in Ruby 3.2.");
return Qfalse;
} Возвращает false. Этот метод устарел и будет удалён в Ruby 3.2.
VALUE
rb_obj_tap(VALUE obj)
{
rb_yield(obj);
return obj;
} Передаёт self в блок и затем возвращает self. Основное назначение этого метода — «подключение» к цепочке методов для выполнения операций над промежуточными результатами в цепочке.
(1..10) .tap {|x| puts "original: #{x}" }
.to_a .tap {|x| puts "array: #{x}" }
.select {|x| x.even? } .tap {|x| puts "evens: #{x}" }
.map {|x| x*x } .tap {|x| puts "squares: #{x}" }
# File lib/bundler/vendor/thor/lib/thor/rake_compat.rb, line 41
def task(*)
task = super
if klass = Bundler::Thor::RakeCompat.rake_classes.last # rubocop:disable AssignmentInCondition
non_namespaced_name = task.name.split(":").last
description = non_namespaced_name
description << task.arg_names.map { |n| n.to_s.upcase }.join(" ")
description.strip!
klass.desc description, Rake.application.last_description || non_namespaced_name
Rake.application.last_description = nil
klass.send :define_method, non_namespaced_name do |*args|
Rake::Task[task.name.to_sym].invoke(*args)
end
end
task
end static VALUE
rb_obj_yield_self(VALUE obj)
{
RETURN_SIZED_ENUMERATOR(obj, 0, 0, rb_obj_size);
return rb_yield_values2(1, &obj);
} Передаёт self в блок и возвращает результат блока.
3.next.then {|x| x**x }.to_s #=> "256"
"my string".yield_self {|s| s.upcase } #=> "MY STRING"
Хорошее использование then — передача значений в цепочках методов:
require 'open-uri'
require 'json'
construct_url(arguments).
then {|url| open(url).read }.
then {|response| JSON.parse(response) }
При вызове без блока метод возвращает Enumerator, что можно использовать, например, для условного прерывания цепочки:
# meets condition, no-op 1.then.detect(&:odd?) # => 1 # does not meet condition, drop value 2.then.detect(&:odd?) # => nil
# File lib/timeout.rb, line 122
def timeout(*args, &block)
warn "Object##{__method__} is deprecated, use Timeout.timeout instead.", uplevel: 1
Timeout.timeout(*args, &block)
end 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()) {
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
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».
# File ext/psych/lib/psych/core_ext.rb, line 12
def to_yaml options = {}
Psych.dump self, options
end Преобразует объект в YAML. См. Psych.dump для получения дополнительной информации о доступных options.
VALUE
rb_obj_trust(VALUE obj)
{
rb_warning("Object#trust is deprecated and will be removed in Ruby 3.2.");
return obj;
} Возвращает объект. Этот метод устарел и будет удалён в Ruby 3.2.
VALUE
rb_obj_untaint(VALUE obj)
{
rb_warning("Object#untaint is deprecated and will be removed in Ruby 3.2.");
return obj;
} Возвращает объект. Этот метод устарел и будет удалён в Ruby 3.2.
VALUE
rb_obj_untrust(VALUE obj)
{
rb_warning("Object#untrust is deprecated and will be removed in Ruby 3.2.");
return obj;
} Возвращает объект. Этот метод устарел и будет удалён в Ruby 3.2.
VALUE
rb_obj_untrusted(VALUE obj)
{
rb_warning("Object#untrusted? is deprecated and will be removed in Ruby 3.2.");
return Qfalse;
} Возвращает false. Этот метод устарел и будет удалён в Ruby 3.2.
# File lib/irb/xmp.rb, line 165 def xmp(exps, bind = nil) bind = IRB::Frame.top(1) unless bind xmp = XMP.new(bind) xmp.puts exps xmp end
Удобный метод, доступный только при подключении стандартной библиотеки IRB::XMP.
Создаёт новый объект XMP, используя заданные выражения в качестве параметра exps, и необязательную привязку в качестве bind, или использует глобальную привязку. Затем вычисляет заданные выражения в режиме подсказки :XMP.
Например:
require 'irb/xmp' ctx = binding xmp 'foo = "bar"', ctx #=> foo = "bar" #==>"bar" ctx.eval 'foo' #=> "bar"
См. XMP.new для получения дополнительной информации.
static VALUE
rb_obj_yield_self(VALUE obj)
{
RETURN_SIZED_ENUMERATOR(obj, 0, 0, rb_obj_size);
return rb_yield_values2(1, &obj);
} Передаёт self в блок и возвращает результат блока.
3.next.then {|x| x**x }.to_s #=> "256"
"my string".yield_self {|s| s.upcase } #=> "MY STRING"
Хорошее использование then — передача значений в цепочках методов:
require 'open-uri'
require 'json'
construct_url(arguments).
then {|url| open(url).read }.
then {|response| JSON.parse(response) }
При вызове без блока метод возвращает Enumerator, что можно использовать, например, для условного прерывания цепочки:
# meets condition, no-op 1.then.detect(&:odd?) # => 1 # does not meet condition, drop value 2.then.detect(&:odd?) # => nil
Ruby Core © 1993–2017 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.