Re: Verhalten von Modulen und Mixins

"Florian G. Pflug" <[email protected]> Sat, 25 Jan 2003 04:31:53 +0100
Newsgroups gmane.comp.lang.ruby.german
Message-ID <[email protected]>
On Tue, Jan 21, 2003 at 05:18:14PM +0100, Winfried Mueller wrote:
> - auf Methoden in Modulen, die mit dem "Modulname." beginnen,
> kann man von außen zugreifen, auf andere nicht:
> 
> module Test
>   def Test.Foo          #-> Zugriff von außen möglich
>     "Ich bin Test.Foo"
>   end
>   def Foo               #-> Zugriff von außen nicht möglich
>     "Ich bin Foo"
>   end
> end 
yep

> - bei Mixins ist es so, dass nur Methoden ohne vorangestellten
> "Modulnamen." included werden, und zwar als Instanzmethode.
yep - wenn du mit "inlude" mix-inst (siehe unten)

> Methoden in Modulen, die den "Modulnamen." vorangestellt
> bekommen, scheinen in keiner Weise übernommen zu werden. (Im
> obigen Beispiel also nur Foo, nicht Test.Foo)
yep - in der default-implementierung (siehe unten)

> - Über Mixins ist es nur möglich, Instanzmethoden in Klassen zu
> includen, man kann keine Klassenmethoden über Mixins erstellen.
mit include schon.... mit extend gehen auch klassenmethoden (siehe unten)

Also, hier meine Sichtweise:

module und klassen (die klasse "klasse" is btw von der klasse "modul"
abgeleitet) sind ja in ruby object wie jedes andere - und haben unter
anderem folgende methoden:

module::include (aModule)
	ruft aModule::append_features (self) auf.

module::append_features(aModule)
	fügt alle Konstanten und member-funktionen ins module aModule ein.
	d.h - ein modul stellt selbst die funktion bereit, um es in ein anderes
	modul/klasse einzufügen

object::extend(aModule)
	ruft aModule::object_extend(self) auf

module::extend_object(anObject)
	fügt die funktionen und Konstanten des moduls in anObject ein.
	dabei wird _nicht_ die klasse von anObject geändert, sondern von dieser
	klasse wird eine anonyme klasse abgeleitet, die die neue klasse von
	anObject wird. In diese anonyme klasse werden die funktionen von anObject
	eingetragen.

Da eine Klasse selbst ein Object ist (und auch von Object abgeleitet ist),
kann man innerhalb einer klassendefinition auch
extend()
aufrufen. Damit werden dem _Klassenobject_ die modulfunktionen als
memberfunktionen hinzugefügt (eigentlich wird wieder ne anonyme subklasse
gebildet, diesmal aber von der metaklasse unserer klasse, 
aber davon merkt man eh nix). Weil die funktionen jetzt aber im endeffekt in
der metaklasse landen, werden sie klassenfunktionen... (!)

Also, langer rede kurzer sinn, mit "extend" fügt man modulfunktionen als
klassenfunktionen ein, mit "include" als instanzfunktionen

module Foo
	def Bar
		puts "foobar"
	end
end

class Qux
	include Foo
end

clas Quux
	extend Foo
end

Foo::new.Bar() #gibt "foobar" aus
Quux::Bar() #gibt "foobar" aus

Ich hoffen ich habe mehr unklarheiten beseitigt als geschafft... falls
nicht, sorry - so ganz sicher fühl ich mich mit objekten/klassen/metaklasse
auch noch nicht.... ;-)

greetings, Florian Pflug