Ruby-Programmierung: Module

Zurück zum Inhaltsverzeichnis.

Unter Modulen ist es möglich Rubycode zu einer logischen Einheit zusammenzufassen, das kann sich je nach Anwendungszweck auf einzelne Methoden, Konstanten oder ganze Klassen beziehen. Dadurch wird es möglich diese Bündel zusammen zu verwenden und Konflikte zwischen Namen zu verhindern.

Module werden wie Klassen definiert und folgen den gleichen Namenskonventionen. Die parallelen zwischen Klassen und Modulen in Bezug auf Kapselung des Codes geht noch weiter, so dass das folgende Skript die gleiche Funktionalität auch mit class Example haben würde. Bei der Verwendung von Modulen erreichen Sie nichts, was nicht auch durch Verwendung von Klassen möglich wäre. Die Verwendung eines Moduls sollten Sie immer dann einer Klasse vorziehen, wenn die Bildung einer Instanz keinen Sinn hat oder mehrere Klassen zusammengehören.

module Example
  class Hello
    def self.world
      puts "Hello World!"
    end
  end
end

Example::Hello.world

Modulfunktionen

Bearbeiten

Neben der Möglichkeit Module in Objekte einzufügen, was im Kapitel Vererbung besprochen wird, ist es nur möglich die Modulfunktionen eines Moduls zu benutzen, da Instanzmethoden eine Objektinstanz voraussetzen. Sie unterscheiden sich genauso wie Klassen- und Instanzmethoden der Objekte aus dem vorherigen Kapitel.

Das folgende Listing definiert mehrere Methoden für das Modul. Der Zugriff auf alle Methoden erfolgt gleich mit Example::METHOD.

module Example
  def one
    puts "module_function"
  end
  module_function :one
  
  def Example::two
    puts "Example::two"
  end
  
  def self.three
    puts "self.three"
  end
end

Wenn keine Namenskonflikte vorliegen, kann man ein Module in den aktuellen Namensraum einfügen durch die Verwendung include. Mit dem oben definierten Module also so:

include Example
one

Wenn vorher eine Methode exisitert, die mit dem include in Konflikt steht, wird die Methode nicht überschrieben und die Modulmethode ist weiterhin nur über Example::one aufrufbar.

Namensraumoperator

Bearbeiten

Der Operator :: beschreibt der Maschine, wie sie einen bestimmten Namen suchen muss. Im obigen Beispiel mit Example::one wird also bestimmt, dass es zuerst nötig ist, eine Klasse oder ein Modul mit dem Namen Example zu suchen und dann in diesem Modul die Methode mit dem Namen one. Dabei werden verwendete Aufrufe innerhalb dieser Methoden dann von innen nach außen gesucht, was unter bestimmten Umständen zu Problem führen kann.

module Example
  def self.random_string
    String.new("abc123")
  end

  class String
  end
end

puts Example::random_string

Das obige Skript definiert ein Modul, das eine Methode und eine Klasse enthält. Die Methode soll einen String anlegen und wird aufgerufen. Das Problem daran ist, dass beim Aufruf von random_string nun in den Namensräumen von innen nach außen nach einer Klasse String gesucht wird. Der Konstruktor der Klasse Example::String erhält jedoch keine Parameter, sodass das obige Skript mit einem Fehler abbricht. Es ist möglich, explizit die Stringklasse des globalen Namensraums zu verwenden durch das Präfix ::. Das Skript beendet erwartungsgemäß durch Ändern der entsprechenden Zeile zu ::String.new("abc123").