webentwicklung-frage-antwort-db.com.de

Wie verwendet man globale Variablen oder konstante Werte in Ruby?

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?

66

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.

53
Igor

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:

  1. 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.

  2. 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.

110
Chuck

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.

10
mikej