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
include
eingebunden, werden alle Modulmethoden zu Instanzmethoden der einbindenden Klasse. - Wird ein Modul mittels
extend
eingebunden, werden alle Modulmethoden zu Klassenmethoden der einbindenden Klasse. - es ist (in Rails) durchaus üblich, ein Modul
Foo
zu definieren, welches dann mitinclude Foo
eingebunden wird, sowie ein UntermodulFoo::ClassMethods
, welches mittelsextend Foo::ClassMethods
eingebunden 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 mittelsinclude
eingebunden, müssen alle@foo
's also Instanzvariablen der Objekte werden; wird es mitextend
eingebunden, sind es eben Instanzvariablen der Klasse (und NICHT etwa Klassenvariablen oder so...) - Klassenvariablen (
@@bar
) werden beiinclude
einfach übernommen -- sprich, was im Modul eine "Klassen"variable war, wird auch in (den Instanzen) der einbindenden Klasse als Klassenvariable erhalten bleiben. Beiextend
jedoch 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?