Pregunta

Viniendo de un fondo C ++ tengo curiosidad por la asignación de objetos en Ruby. Qué consideraciones (si las hay) deben hacerse para las siguientes asignaciones de objetos:

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
¿Fue útil?

Solución

Si está familiarizado con C ++, es posible que desee considerar cada variable en Ruby, instancia o de otra manera, como referencia a otro objeto. Dado que todo en Ruby es un objeto, incluso nil, que es de tipo nilclass, esto es cierto bajo todas las circunstancias.

Para determinar a qué objeto está haciendo referencia, puede usar el object_id método para diferenciar. Eso es similar a la conversión a un puntero que usa & En C ++.

Considera esto:

a = "foo"
b = a

a.object_id == b.object_id
# => true

Ya que a es una referencia a esa cadena, y b es una copia de a, entonces son en realidad diferentes referencias al mismo objeto.

Esto es importante porque las operaciones que modifican un objeto afectan todas las referencias a eso por igual:

a << "bar"
# => "foobar"
b
# => "foobar"

Sin embargo, operaciones que crean un nuevo El objeto no modificará todas las copias:

a += "baz"
# => "foobarbaz"
b
# => "foobar"

Muchos métodos en Ruby son identificados por un ! Para distinguir las versiones en el lugar versus las nuevas copias, pero este no siempre es el caso, por lo que debe estar familiarizado con cada método para estar seguro.

Generalmente una tarea reemplazará una referencia antigua con una nueva, por lo que, como regla general, el pulgar, = Reemplazará las viejas referencias. Esto aplica a +=, -=, ||=, &&= y así.

Editar: Actualizado basado en el comentario de Phrogz sobre el uso ObjectSpace._id2ref(object_id) para convertir un identificador de objeto en un objeto.

Otros consejos

Como todo es un objeto en Ruby, la asignación siempre es por referencia.

Entonces, tomando su clase como entrada, la siguiente será la salida para varias operaciones:

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

Reescribiría esto como:

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

De esta manera, realmente está utilizando los métodos getter/setter definidos por attr_accessor Dentro de tu clase

Cuando asignas q = n, Q solo hace referencia a la misma ubicación de memoria que se estableció para n. El objeto no se copia.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top