Ich habe ein Programm, das aussieht wie:
$offset = Point.new(100, 200);
def draw(point)
pointNew = $offset + point;
drawAbsolute(point)
end
draw(Point.new(3, 4));
Die Verwendung von $offset
scheint ein bisschen komisch.
Wenn ich in C etwas außerhalb einer Funktion definiere, ist es automatisch eine globale Variable. Warum muss es in Ruby sein $offset
, kann offset
und kann aber nicht global sein? Wenn ja offset
, dann ist es ein Einheimischer? Aber lokal wo, weil es sich sehr global anfühlt.
Gibt es bessere Möglichkeiten, den obigen Code zu schreiben? Die Verwendung von $offset
mag zunächst etwas hässlich erscheinen.
Update: Ich kann diesen Offset in eine class
Definition einfügen, aber was ist, wenn zwei oder mehrere Klassen diese Konstante verwenden müssen? Muss ich in diesem Fall noch ein definieren $offset
?
ruby
global-variables
Unpolarität
quelle
quelle
Antworten:
Eine Sache, die Sie erkennen müssen, ist, dass in Ruby alles ein Objekt ist. Wenn Sie Ihre Methoden nicht in
Module
oder definierenClass
, wird sie von Ruby in dieObject
Klasse eingefügt. Ihr Code ist also lokal für denObject
Bereich.Ein typischer Ansatz für die objektorientierte Programmierung besteht darin, die gesamte Logik innerhalb einer Klasse zu kapseln:
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)
Hoffe das klärt ein bisschen.
quelle
Object
Bereich: die für Variablen ohne das stimmt$
Präfix, aber im Gegensatz dazu Methoden Sie dort gesetzt sind global (während auch private Mitglieder der immerObject
Klasse).Point
Objekte auf einen bestimmten konstanten Versatz beziehen, kann ich einen Versatz (x, y) als Klassenkonstante haben, so dass derdraw_absolute()
diese Klassenkonstante als Versatz verwendetDer variable Umfang in Ruby wird bis zu einem gewissen Grad durch Siegel gesteuert. Variablen, die mit beginnen,
$
sind global, Variablen mit@
sind Instanzvariablen,@@
bedeuten Klassenvariablen und Namen, die mit einem Großbuchstaben beginnen, sind Konstanten. Alle anderen Variablen sind Einheimische. Wenn Sie eine Klasse oder Methode öffnen, ist dies ein neuer Bereich, und im vorherigen Bereich verfügbare Lokale sind nicht verfügbar.Ich ziehe es im Allgemeinen vor, das Erstellen globaler Variablen zu vermeiden. Es gibt zwei Techniken, die im Allgemeinen den gleichen Zweck erreichen, den ich für sauberer halte:
Erstellen Sie eine Konstante in einem Modul. In diesem Fall würden Sie also alle Klassen, die den Offset benötigen, in das Modul einfügen
Foo
und eine Konstante erstellenOffset
, damit alle Klassen darauf zugreifen könnenFoo::Offset
.Definieren Sie eine Methode für den Zugriff auf den Wert. Sie können die Methode global definieren, aber ich denke, es ist besser, sie in ein Modul oder eine Klasse zu kapseln. Auf diese Weise sind die Daten dort verfügbar, wo Sie sie benötigen, und Sie können sie bei Bedarf sogar ändern. Die Struktur Ihres Programms und der Besitz der Daten werden jedoch klarer. Dies entspricht eher den OO-Designprinzipien.
quelle
Einer der Gründe, warum die globale Variable ein Präfix benötigt (als "Siegel" bezeichnet), ist, dass Sie in Ruby im Gegensatz zu C Ihre Variablen nicht deklarieren müssen, bevor Sie sie zuweisen. Das Siegel wird verwendet, um den Umfang der Variablen explizit darzustellen.
Ohne ein bestimmtes Präfix für Globals bezieht sich eine angegebene Anweisung
pointNew = offset + point
in Ihrerdraw
Methodeoffset
auf eine lokale Variable in der Methode (und führtNameError
in diesem Fall zu einer). Das Gleiche gilt für@
Verweisvariablen und@@
für Klassenvariablen.In anderen Sprachen , die expliziten Erklärungen wie verwenden
C
,Java
usw. die Platzierung der Deklaration wird verwendet , um den Umfang zu steuern.quelle
$
Hilfe von Ruby, ob es sich um eine neue oder eine vorhandene Variable handelt? Wenn Sie dem$foo
Gedanken etwas zuweisen, dass es etwas gibt$foo
, aber es passiert, dass es noch nichts$foo
gibt oder es nur von jemandem entfernt wurde, wird Ruby$foo
trotzdem als neues globales Objekt erstellt, obwohl es nicht dasselbe ist, das$foo
Sie gedacht haben.$
wird das Fehlen ordnungsgemäßer Erklärungen nicht beheben.Ich denke, es ist lokal für die Datei, die Sie als Offset deklariert haben. Betrachten Sie jede Datei als eine Methode für sich.
Vielleicht das Ganze in eine Klasse einordnen und dann Offset zu einer Klassenvariablen machen mit
@@offset = Point.new(100, 200);
?quelle