2009-02-28 28 views
0

Ich bin wirklich neu in Ruby. Und durch neue - weniger als 16 Stunden, aber mein Chef gab mir etwas Ruby Code hinzuzufügen. Ich fand jedoch, dass es eine riesige Datei war und überhaupt nicht modular, also beschloss ich, sie zu säubern. Jetzt, da ich es in mehrere Dateien/Klassen aufgeteilt habe (im Allgemeinen 1 Klasse pro Datei), habe ich Probleme, es zusammenzufügen, damit es wieder funktioniert. Ursprünglich war alles Teil derselben Klasse, also funktionierten die Anrufe, aber es sah hässlich aus und es brauchte einen ganzen Arbeitstag, um es herauszufinden. Ich möchte das für die Zukunft vermeiden, da dieser Code noch viel größer wird, bevor er fertig ist.Zugriff auf Instanzvariablen von einer Klasse innerhalb einer anderen Klasse

Mein Hauptproblem sieht wie folgt aus (vereinfacht, natürlich):

class TestDevice 
    def initialize 
    @loghash = { } 
    .... 
    end 
end 

class Log 
    def self.msg(identifier, level, section, message) 
    ... 
    @loghash[identifier] = { level => { section => message }} 
    ... 
    end 
end 

device = TestDevice.new 

Danach ruft es auf andere Klassenmethoden aus, und die Klassenmethoden verweisen zurück auf die Klasse Log für ihre Protokollierung Bedürfnisse. Natürlich muss Log auf "device.loghash" zugreifen, um die Informationen in diesem Hash zu protokollieren. Aber ich kann nicht herausfinden, wie ich das erreichen kann, wenn ich den Inhalt von "loghash" nicht an jede Methode weitergebe, so dass sie diese wiederum weitergeben und den Wert dann an den Ursprungspunkt zurückgeben und ihn dann protokollieren kann am Ende, aber das scheint wirklich ungeschickt und peinlich.

Ich hoffe, ich bin wirklich nur etwas fehlt.

Antwort

4

Um Accessoren für Instanzvariablen auf einfache Weise zu erstellen, verwenden Sie attr_accessor.

class TestDevice 
    attr_accessor :loghash 

    def initialize 
    @loghash = { } 
    .... 
    end 
end 

Sie können einen Accessor auch manuell definieren.

Dies ist effektiv, was attr_accessor hinter den Kulissen tut.

+0

Sollte sein "Dies ist effektiv, was attr_accessor hinter den Kulissen tut." –

+0

Richtig du bist. Danke, dass du das verstanden hast. – Chuck

2

Wie wird das Geräteobjekt als Parameter an die Funktion msg übergeben? (Ich gehe davon aus, dass es in Ihrem Programm viele Geräte geben kann, ansonsten können Sie das Singleton-Muster verwenden).

class TestDevice 
    attr_accessor :loghash 

    def initialize 
    @loghash = { } 
    .... 
    end 
end 

class Log 
    def self.msg(device, identifier, level, section, message) 
    ... 
    device.loghash[identifier] = { level => { section => message }} 
    ... 
    end 
end 
1

Sie müssen also die Regeln von Ruby Scoping lernen.

Ruby-Variablen haben unterschiedlichen Umfang je nach Vorwahl:

  • $global_variables Start mit einem $ und sind für jedermann zugänglich.
  • @instance_variables starten mit einem einzigen @, und sind mit dem aktuellen Wert von self gespeichert. Wenn zwei Bereiche den gleichen Wert von self teilen (sie sind beide Instanzmethoden, zum Beispiel), dann teilen beide die gleichen Instanzvariablen
  • @@class_variable Start mit @@ und werden mit der Klasse gespeichert. Sie sind freigegeben zwischen allen Instanzen einer Klasse - und alle Instanzen der Unterklassen dieser Klasse.
  • Constants beginnen mit einem Großbuchstaben, und können alle Großbuchstaben sein. Wie Klassen Variablen, sie sind mit der aktuellen self.class gespeichert, aber sie auch tröpfeln die Hierarchie - also, wenn Sie eine Klasse in einem Modul, die Instanzen der Klasse haben Zugriff auf die Konstanten des Moduls. Konstanten, die außerhalb einer Klasse definiert sind, haben einen globalen Gültigkeitsbereich. Beachten Sie, dass eine konstante Variable bedeutet, dass das Objekt, das an die Konstante gebunden ist, sich nicht ändert, nicht dass das Objekt selbst den internen Zustand ändert.
  • local_variables Start mit einem Kleinbuchstaben

Sie können here mehr über Umfang lesen.

Lokale Variablen Regeln Scoping sind vor allem Standard - sie in verfügbar sind alle subscopes von dem, in dem sie except definiert, wenn wir in ein Modul, Klasse bewegen, oder Methodendefinition. Wenn wir also auf dem Code schauen von Ihrer Antwort

class TestDevice 
    attr_accessor :loghash 
    def initialize 
    @loghash = { } 
    end 
end 

device = TestDevice.new 

class Somethingelse 
    def self.something 
    device.loghash='something here' # doesn't work 
    end 
end 

Der Umfang des device lokalen Variable in der Toplevel definiert umfasst nicht die Somethingelse.something Methodendefinition. Daher ist die device lokale Variable, die in der Somethingelse.something Methodendefinition verwendet wird, eine andere (leere) Variable. Wenn das Scoping auf diese Weise funktionieren soll, sollten Sie eine konstante oder eine globale Variable verwenden.

class TestDevice 
    attr_accessor :loghash 
    def initialize 
    @loghash = { } 
    end 
end 

DEVICE = TestDevice.new 
$has_logged = false 

class Somethingelse 
    def self.something 
    DEVICE.loghash='something here' 
    $has_logged = true 
    end 
end 

p DEVICE.loghash # prints `{}` 
p $has_logged  # prints `false` 
Somethingelse.something 
p DEVICE.loghash # prints `"something here"` 
p $has_logged  # prints `true` 
Verwandte Themen