Als Ergänzung zu meinem letzten Eintrag zum Thema "Rubys Objektmodell" folgen ein paar Notizen dazu, wie sich Module in das Gefüge einfügen (müssen sie ja irgendwie, sonst wäre es kein Gefüge ;-))
- Wird ein Modul mittels
includeeingebunden, werden alle Modulmethoden zu Instanzmethoden der einbindenden Klasse. - Wird ein Modul mittels
extendeingebunden, werden alle Modulmethoden zu Klassenmethoden der einbindenden Klasse. - es ist (in Rails) durchaus üblich, ein Modul
Foozu definieren, welches dann mitinclude Fooeingebunden wird, sowie ein UntermodulFoo::ClassMethods, welches mittelsextend Foo::ClassMethodseingebunden wird. Diese Praxis habe ich einfach mal so übernommen.
So viel zu den Methoden. Doch was ist mit den Variablen? Wie wir alle wissen, werden Klassenvariablen weitervererbt, Instanzvariablen jedoch nicht (irgendwie logisch...). Aber bei Modulen...?
- Da ein Modul nicht instanziiert werden kann, kann es auch keine Instanzvariablen (
@foo) haben -- ganz einfach. Wird ein Modul mittelsincludeeingebunden, müssen alle@foo's also Instanzvariablen der Objekte werden; wird es mitextendeingebunden, sind es eben Instanzvariablen der Klasse (und NICHT etwa Klassenvariablen oder so...) - Klassenvariablen (
@@bar) werden beiincludeeinfach übernommen -- sprich, was im Modul eine "Klassen"variable war, wird auch in (den Instanzen) der einbindenden Klasse als Klassenvariable erhalten bleiben. Beiextendjedoch sind alle im Modul definierten Klassenvariablen nur für die im Modul definierten Methoden erreichbar! Alle Versuche, aus dem Kontekt der Klasse (oder einer ihrer Instanzen) an sie heranzukommen, sind bei mir bislang gescheitert.
An einem Beispiel zeigt sich so was immer schön:
module Foo
@@truth = 42
def say_the_truth
p @@truth
end
end
class Bar
include Foo
end
Bar.new.say_the_truth # 42 *SMILE*
class FooBar < Bar
def say_something
p @@truth
end
end
FooBar.new.say_something # 42 *SMILE*
class Baz
extend Foo
def say_something
p @@truth
end
end
Baz.say_the_truth # 42 *SMILE*
Baz.new,say_something # PENG! WUMMS! "NameError: uninitialized class variable @@truth in Baz" ... *Autsch*
Alles klar?
