About

This page contains a single entry from the blog posted on January 25, 2008 12:18 AM.

The previous post in this blog was Ein weiterer Rails-Bug.

The next post in this blog is Ein paar Worte zu Modulen in Ruby.

Many more can be found on the main index page or by looking through the archives.

Powered by
Movable Type 3.31

« Ein weiterer Rails-Bug | Main | Ein paar Worte zu Modulen in Ruby »

Rubys Objektmodell

OK, was ich jetzt hier schreibe ist nichts neues und auch schon auf viel bessere Art und Weise von Why the Lucky Stiff beschrieben worden. Jedenfalls trieb mich ein Bug in Consolvix dazu, mich nochmals intensiver mit dem Thema Metaprogrammierung und dem Ruby-Objektmodell auseinanderzusetzen. Es folgen ein Paar Notizen.

  • Objekte in Ruby können nur Variablen aufnehmen -- Ein Ruby-Objekt hat keine Methoden
  • Objekte sind in erster Linie dies: Objekte. Erst in zweiter Linie sind sie Instanzen einer Klasse. Auch Klassen sind Objekte (ABER auf C-Quellcode-Ebene sind Object und Class zwei verschiedene Structs -- ich halte diese Information für wichtig, wenn man wirklich blicken will, warum diese Class-Objekt-Abhängigkeit keine unendliche Rekursion mit sich bringt)
  • Objekt-/Instanz-Methoden befinden sich in der Klasse, von der sich das Objekt ableitet. Eine Klasse ist nicht ein statisches, abstraktes Dingda, sondern ein Singleton-Objekt. Ein Objekt, das (Klassen-)Variablen UND Methoden aufnehmen kann. Eine Klasse eben. (Und hier würde dann die Rekursion einsetzen ;-))
  • Klassenmethoden befinden sich -- nein, nicht in der Klasse, die ja ein Objekt ist, sondern in der Klasse, die meistens Metaklasse genannt wird.
  • Klassen vererben ihre Methoden ihren Unterklassen. Somit steht, wenn man eine Klasse um eine neue Methode bereichert, sofort sämtlichen Unterklassen und sämtlichen Instanzen der Klasse diese Methode zur Verfügung. Wenn man aber einem einzelnen Objekt an dieser Stelle eine andere Implementierung dieser Methode geben möchte, so kann man dem Objekt diese Methode über die Metaklasse dieses Objektes zur Verfügung stellen. Methoden werden zuerst in der Metaklasse dann erst in der Klassenhierachie gesucht.
  • Das Konzept der Vererbung erweitert eine Klassenhierachie vertikal, während Module die Klassenhierachie horizontal erweitern -- man könne also sagen, dass das Konzept der Metaklassen die Hierachie in der tiefe erweitern -- aber das klingt gleich wieder so esotherisch...
  • Metaklassen können, da diese wiederum Objekte sind, selbst auch wieder Metaklassen enthalten. Eine Veränderung der Metaklasse einer Metaklasse einer Klasse zieht jedoch keinerlei Konsequenzen für die Klasse nach sich. Außerdem ist es sehr unwahrscheinlich, dass von diesem Konzept jemals jemand Gebrauch machen wird (OK, ich werde meinen kranken Geist darauf ansetzen, in einer freien Minute etwas passendes zu finden ;-))

Folgendes ER-Diagramm hab ich nach meinem Verständnis des Sachverhaltes zusammengestellt. Wenn jemand darin einen grundlegenden Fehler entdeckt, bitte sofort melden!

Dieses Klassendiagramm habe ich nach dem ASCII-Diagram aus einem (vermutlich bekannten) Post in der Ruby-Talk-Mailingliste gebastelt. Es stellt die Abhängigkeit der Klassen und Objekte untereinander dar. Wie man sieht, erbt letztendlich alles von Object. Die Klassen mit eingeklammerten Namen sind die jeweiligen Meta-Klassen (bzw. Singleton-Klassen-Instanzen...).

RubyObjectModelInheritances.png

Ich finde, dass das Bild etwas klarer wird, wenn man die Vererbung durch eine gerichtete Beziehung der Objekte untereinander ersetzt. super zeigt somit immer auf das Objekt der Elternklasse während self auf das Objekt der Singleton-Klasse zeigt.

RubyObjectModelReferences.png

So hat man im Wesentlichen die Abbildung des Ruby-Objektmodells auf C-Ebene vor sich: Vererbung und "magische Meta-Dingsda" sind nichts weiter als Structs, von denen einige lediglich Variablen, andere auch Methoden referenzieren können... der ganze Zauber gelüftet, aber eine Menge mehr Klarheit geschaffen :)

Zu dem ganzen ist anzumerken, dass nicht zu jedem Objekt a priori eine Singletonklasse existiert -- das würde unendlich viel Speicher erfordern. Eine Singletonklasse wird nur dann erstellt, wenn sie explizit angefordert wird, und zwar über

class Foo
  # ...
end

obj = Foo.new

class << obj
  # hier sind wir im Kontext der Metaklasse von obj!
end

class << Foo
  # hier sind wir im Kontext der Metaklasse von Foo!
end

class Foo
  class << self
    class << self
      # im Kontext der Metaklasse der Metaklasse von Foo ;-)
    end
  end
end

Alles klar? Nicht? Dann hilft nur lesen des o.g. Artikels von Why the Lucky Stiff oder sich einfach mit anderen Dingen beschäftigen...

TrackBack

TrackBack URL for this entry:
http://www.innoq.com/movabletype/mt-tb.cgi/2985

Post a comment

(If you haven't left a comment here before, you may need to be approved by the site owner before your comment will appear. Until then, it won't appear on the entry. Thanks for waiting.)