Ich habe ein Programm, das so aussieht:
$offset = Point.new(100, 200);
def draw(point)
pointNew = $offset + point;
drawAbsolute(point)
end
draw(Point.new(3, 4));
die Verwendung von $offset
scheint etwas seltsam.
Wenn ich in C etwas außerhalb einer Funktion definiere, ist es automatisch eine globale Variable. Warum muss es in Ruby) $offset
Sein, kann aber nicht offset
sein und ist es immer noch global? Wenn es offset
ist, dann ist es ein lokaler? Aber lokal wo, weil es sich sehr global anfühlt.
Gibt es bessere Möglichkeiten, den obigen Code zu schreiben? Die Verwendung von $offset
Scheint zunächst etwas hässlich.
Update: Ich kann diesen Offset in eine class
Definition einfügen, aber was ist, wenn zwei oder mehrere Klassen diese Konstante verwenden müssen? In diesem Fall muss ich noch einen $offset
Definieren?
Eine Sache, die Sie wissen müssen, ist in Ruby alles ist ein Objekt. Wenn Sie Ihre Methoden nicht in Module
oder Class
definieren, = Ruby wird in die Klasse Object
eingefügt. Ihr Code ist also lokal für den Gültigkeitsbereich Object
.
Ein typischer Ansatz zur objektorientierten 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.
Der Gültigkeitsbereich von Variablen in Ruby wird zu einem gewissen Grad von Siegeln gesteuert. Variablen, die mit $
Beginnen, sind global, Variablen mit @
Sind Instanzvariablen, @@
bedeutet, dass Klassenvariablen und Namen, die mit einem Großbuchstaben beginnen, Konstanten sind. Alle anderen Variablen sind lokale Variablen. Wenn Sie eine Klasse oder Methode öffnen, ist dies ein neuer Bereich, und die im vorherigen Bereich verfügbaren lokalen Variablen sind nicht verfügbar.
Generell ziehe ich es vor, keine globalen Variablen zu erstellen. Es gibt zwei Techniken, die im Allgemeinen den gleichen Zweck erreichen, den ich als sauberer betrachte:
Erstellen Sie eine Konstante in einem Modul. In diesem Fall würden Sie also alle Klassen, die den Offset benötigen, in das Modul Foo
einfügen und eine Konstante Offset
erstellen, damit alle Klassen auf Foo::Offset
Zugreifen können.
Definieren Sie eine Methode, um auf den Wert zuzugreifen. Sie können die Methode global definieren, aber ich denke, es ist besser, sie in einem Modul oder einer Klasse zu kapseln. Auf diese Weise stehen die Daten dort zur Verfügung, wo Sie sie benötigen, und Sie können sie bei Bedarf sogar ändern, aber die Struktur Ihres Programms und die Eigentümerschaft der Daten werden klarer. Dies entspricht eher den OO Designprinzipien.
Einer der Gründe, warum die globale Variable ein Präfix ("Sigil" genannt) benötigt, ist, dass Sie in Ruby im Gegensatz zu C Ihre Variablen nicht deklarieren müssen, bevor Sie ihnen ein Präfix zuweisen. Das Siegel wird verwendet, um den Gültigkeitsbereich der Variablen zu bestimmen.
Ohne ein spezielles Präfix für Globale, gegeben eine Anweisung pointNew = offset + point
in Ihrer draw
-Methode verweist dann offset
auf eine lokale Variable in der Methode (und führt in diesem Fall zu NameError
). Das selbe für @
bezeichnet Instanzvariablen und @@
für Klassenvariablen.
In anderen Sprachen, die explizite Deklarationen wie C
, Java
usw. verwenden, wird die Platzierung der Deklaration verwendet, um den Gültigkeitsbereich zu steuern.