Назначение объекта в Ruby [закрыто
-
27-10-2019 - |
Вопрос
Исходя из фона C ++, мне любопытно, что задание объекта в Ruby. Какие соображения (если таковые имеются) должны быть сделаны для следующих назначений объектов:
class MyClass
attr_accessor :a, :b
def initialize(a, b)
@a = a
@b = b
end
def some_method
puts "#{self.a} #{self.b}"
end
end
m = MyClass.new("first", "last")
n = MyClass.new("pizza", "hello")
q = n
q.some_method
Решение
Если вы знакомы с C ++, то вы можете рассмотреть каждую переменную в рубине, экземпляре или ином случае, в качестве ссылки на другой объект. Поскольку все в Руби является объектом, даже nil
, который имеет тип Nilclass, это верно при любых обстоятельствах.
Чтобы определить, на какой объект вы ссылаетесь, вы можете использовать object_id
Метод для дифференциации. Это похоже на преобразование в указатель с использованием &
в C ++.
Учти это:
a = "foo"
b = a
a.object_id == b.object_id
# => true
С a
это ссылка на эту строку, и b
это копия a
, тогда они на самом деле являются разными ссылками на один и тот же объект.
Это важно, потому что операции, которые изменяют объект, влияют на все ссылки на это одинаково:
a << "bar"
# => "foobar"
b
# => "foobar"
Однако операции, которые создают новый Объект не будет изменять все копии:
a += "baz"
# => "foobarbaz"
b
# => "foobar"
Многие методы в Ruby идентифицированы !
Чтобы отличить версии на месте и новой копии, но это не всегда так, поэтому вы должны быть знакомы с каждым методом, чтобы быть уверенным.
Как правило, назначение заменит старую ссылку на новую, поэтому, как правило, =
заменит старые ссылки. Это относится к +=
, -=
, ||=
, &&=
и так далее.
Редактировать: Обновляется на основе комментария Phrogz об использовании ObjectSpace._id2ref(object_id)
Чтобы преобразовать идентификатор объекта в объект.
Другие советы
Поскольку все является объектом в Ruby, назначение всегда является ссылкой.
Итак, взяв свой класс в качестве ввода, следующим образом будет вывод для нескольких операций:
str = "foo"
foo = MyClass.new(str, "bar")
foo.some_method # foo bar
bar = foo
bar == foo # true
bar.some_method # foo bar
str << "bar" # strings are mutable on ruby, so str is now "foobar"
foo.some_method # foobar bar
bar.some_method # foobar bar
Я бы переписал это как:
class MyClass
attr_accessor :a, :b
def initialize(a, b)
self.a = a
self.b = b
end
def some_method
puts "#{a} #{b}"
end
end
Таким образом, вы на самом деле используете методы Getter/Setter, определяемые attr_accessor
В вашем классе
Когда вы назначаете q = n
, Q просто ссылается на то же местоположение памяти, которое было установлено на n. Объект не скопирован.