Вопрос

Исходя из фона 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. Объект не скопирован.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top