Come si usano variabili globali o valori costanti in Ruby?

Ho un programma che assomiglia a:

$offset = Point.new(100, 200); def draw(point) pointNew = $offset + point; drawAbsolute(point) end draw(Point.new(3, 4)); 

l’uso di $offset sembra un po ‘strano.

In C, se definisco qualcosa al di fuori di qualsiasi funzione, è automaticamente una variabile globale. Perché in Ruby deve essere $offset ma non può essere offset ed essere ancora globale? Se è offset , allora è un locale? Ma locale a dove, perché sembra molto globale.

Ci sono modi migliori per scrivere il codice sopra? L’uso di $offset può sembrare un po ‘brutto all’inizio.


Aggiornamento: posso inserire questo offset all’interno di una definizione di class , ma cosa succede se due o più classi hanno bisogno di usare questa costante? In questo caso devo ancora definire un $offset ?

Una cosa che devi realizzare è che in Ruby tutto è un object. Dato che, se non si definiscono i propri metodi all’interno di Module o Class , Ruby lo inserirà nella class Object . Pertanto, il codice sarà locale rispetto all’ambito Object .

Un approccio tipico alla programmazione orientata agli oggetti è incapsulare tutta la logica all’interno di una class:

 class Point attr_accessor :x, :y # If we don't specify coordinates, we start at 0. def initialize(x = 0, y = 0) # Notice that `@` indicates instance variables. @x = x @y = y end # Here we override the `+' operator. def +(point) Point.new(self.x + point.x, self.y + point.y) end # Here we draw the point. def draw(offset = nil) if offset.nil? new_point = self else new_point = self + offset end new_point.draw_absolute end def draw_absolute puts "x: #{self.x}, y: #{self.y}" end end first_point = Point.new(100, 200) second_point = Point.new(3, 4) second_point.draw(first_point) 

Spero che questo chiarisca un po ‘.

Lo scope variabile in Ruby è controllato da sigilli in una certa misura. Le variabili che iniziano con $ sono globali, le variabili con @ sono variabili di istanza, @@ indica le variabili di class e i nomi che iniziano con una lettera maiuscola sono costanti. Tutte le altre variabili sono locali. Quando apri una class o un metodo, questo è un nuovo ambito e i locali disponibili nello scope precedente non sono disponibili.

Generalmente preferisco evitare di creare variabili globali. Esistono due tecniche che generalmente raggiungono lo stesso scopo che considero più pulito:

  1. Crea una costante in un modulo. Quindi in questo caso, inserirai tutte le classi che hanno bisogno dell’offset nel modulo Foo e creerai un Offset costante, quindi tutte le classi potranno accedere a Foo::Offset .

  2. Definire un metodo per accedere al valore. È ansible definire il metodo a livello globale, ma ancora una volta, penso che sia meglio incapsularlo in un modulo o una class. In questo modo i dati sono disponibili dove ne hai bisogno e puoi persino modificarli se necessario, ma la struttura del tuo programma e la proprietà dei dati saranno più chiari. Questo è più in linea con i principi di progettazione OO.

Uno dei motivi per cui la variabile globale ha bisogno di un prefisso (il $ ) è perché in Ruby, a differenza di C, non è necessario dichiarare le variabili prima di assegnarle quindi senza un prefisso specifico per i globals data un’istruzione come offset = Point.new(100, 200) all’interno del tuo metodo di disegno quindi Ruby non saprebbe se ti offset = Point.new(100, 200) alla variabile esistente o crea una nuova variabile locale all’interno del tuo metodo. Lo stesso con il prefisso @ per le variabili di istanza.

Penso che sia locale al file che hai dichiarato offset. Considerare ogni file come un metodo stesso.

Magari inserire l’intera cosa in una class e quindi rendere offset una variabile di class con @@offset = Point.new(100, 200); ?