Domanda

Venendo da un C ++ sfondo Sono curioso di sapere assegnazione oggetto in Ruby. Quali considerazioni (se presente) deve essere fatta per le seguenti assegnazioni di oggetto:

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
È stato utile?

Soluzione

Se si ha familiarità con C ++, allora si potrebbe prendere in considerazione tutte le variabili in Ruby, istanza o altrimenti, come un riferimento a un altro oggetto. Poiché tutto in Ruby è un oggetto, anche nil, che è di tipo NilClass, questo vale in ogni circostanza.

Per determinare quale oggetto fari riferimento, è possibile utilizzare il metodo object_id per differenziare. Questo è simile alla conversione a un puntatore utilizzando & in C ++.

Considerate questo:

a = "foo"
b = a

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

Poiché a è un riferimento a tale stringa e b è una copia di a, allora sono effettivamente differenti riferimenti allo stesso oggetto.

Questo è importante perché le operazioni che modificano un oggetto influenzano ogni riferimento a tale ugualmente:

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

Tuttavia, le operazioni che creano un nuovo oggetto non modificare tutte le copie:

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

Molti metodi in Ruby sono identificati da un ! per distinguere sul posto rispetto alle versioni di nuova copia, ma questo non è sempre il caso, quindi bisogna avere familiarità con ogni metodo, al fine di essere sicuri.

In genere un incarico andrà a sostituire un vecchio di riferimento con uno nuovo, così come regola generale, = sostituirà i vecchi riferimenti. Questo vale per +=, -=, ||=, &&= e così via.

Modifica:. Aggiornamento in base a commento di Phrogz sull'utilizzo ObjectSpace._id2ref(object_id) per convertire un identificatore di oggetto in un oggetto

Altri suggerimenti

Poiché tutto è un oggetto in rubino, assegnazione è sempre in funzione.

Quindi, prendendo la classe come ingresso, il successivo sarà l'output per diverse operazioni:

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

vorrei riscrivere questo come:

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

In questo modo si sta usando i metodi getter / setter definiti dalla attr_accessor all'interno della vostra classe

Quando si q = n assegnare, q solo fa riferimento alla stessa posizione di memoria che è stato fissato per il n. L'oggetto non viene copiato.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top