Die Programmiersprache Ruby

Blog| Forum| Wiki  

Grob gesehen ist ein Modul nichts weiter als ein Behälter für Konstanten, Klassen, Methoden usw. Wenn man jedoch etwas in die Feinheiten geht, erkennt man folgendes:

  1. Module ist die Superklasse von Class. Das bedeutet: Alle Klassen sind zugleich Module und haben deren Möglichkeiten.
  2. Es gibt Module, die nur Modulmethoden beinhalten, sie bilden Namespaces.
  3. Andere Module definieren Instanzmethoden - sie sind Mixins.

Class alias Module: Namespaces

Zwar lässt sich theoretisch jede Klasse als Modul verwenden, praktisch wird das aber nie getan. Es gilt als unsauberer Stil. Eine solche Konstruktion würde nur für Verwirrung sorgen:

1
2
3
4
5
6
7
8
9
10
11
12
class A
  class B
    module C
     
    end
    def hello
      puts "Hello!"
    end
  end
end

A::B.new.hello #=> Hello!

Für Container aller Art werden Module benutzt. Das obige Beispiel sähe so sinnvoller aus:

1
2
3
4
5
6
7
8
9
10
11
module A
  class B
    def hello
      puts "Hello!"
    end
  end
  module C
    
  end
end
A::B.new.hello #=> Hello!

Es stimmt nicht ganz mit dem oberen Code überein, weil das Modul C aus der Klasse B entfernt wurde - dort gehört es nicht hin. Wie man ja bereits am Code gesehen hat, ist die Zugriffssyntax für alles, was im Modul ist, der Geltungsbereichoperator ::. Mithilfe dieses Operators kann man Module in einem Modul, Klassen in einem Modul und Konstanten in einem Modul abrufen:

1
2
3
4
module Mein_Modul
  MEINE_KONSTANTE = 1
end
puts Mein_Modul::MEINE_KONSTANTE #=> 1

Es ist auch möglich, Modulmethoden auf diese Art und Weise abzurufen, aber das ist kein guter Stil und wird als unelegant angesehen. Stattdessen sollte man auf die Syntax für Klassenmethoden zurückgreifen - schliesslich werden Modulmethoden genauso wie Klassenmethoden definiert:

1
2
3
4
5
6
7
8
9
10
11
12
module Mein_Modul
  def self.modulmethode
    puts "Eine Modulmethode!"
  end
  
  def Mein_Modul.zweite_modulmethode
    puts "Noch eine!"
  end
end
Mein_Modul.modulmethode #=> Eine Modulmethode!
#Geht auch, ist aber unelegant: 
Mein_Modul::modulmethode


beim öffnen eines Namespaces sollte man auf die genutzen Konstanten achten die man definiert.

1
2
3
4
5
6
7
8
9
10
module A
  C = true
  module B
    puts C #=> true
  end
end
#aber:
module A::B
  puts C #=> unbekannte Konstante A::B::C
end


Die Namen für Module sollten so gewählt werden, dass sie einmalig sind - durch Rubys Möglichkeit, bestehende Klassen und Module zu bearbeiten, kann es zu Konflikten kommen:

  • Eine Datei "lib1.rb"
module AdvancedFunctions
  def self.function1
    puts "1"
    return 1
  end
end
  • Eine Datei "lib2.rb"
module AdvancedFunctions
  class << AdvancedFunctions
    def function1
      puts "2"
      return 2
    end
  end
end

Wenn ein Programm beide Libs einbindet, kommt es zum Konflikt, weil lib2 die Methode aus lib1 überschreibt:

1
2
3
4
require "lib1"
AdvancedFunctions.function1 #=> 1
require "lib2"
AdvancedFunctions.function1 #=> 2

Also eindeutige Namen verwenden!

Mixins

Zusätzlich kann man Module als Mixins verwenden. Schon einmal probiert, was passiert, wenn man in einem Modul eine Methode so definiert?

1
2
3
4
5
module Mein_Modul
  def meine_methode
    puts "Hello!"
  end
end

Antwort: Gar nichts. Man kann die Methode nicht aufrufen. Warum ist das so? Ganz einfach: Dieses Modul wird als Mixin behandelt, dass seine Methoden einer Klasse zur Verfügung stellen kann:

1
2
3
4
class MeineKlasse
  include Mein_Modul #<== Einbinden des Moduls
end
MeineKlasse.new.meine_methode #=> Hello!

Der Hauptartikel zu Mixins befindet sich im Artikel Vererbung, da mit Mixins häufig Mehrfachvererbung simuliert wird.