next up previous contents index
Search Next: Die Klassenhierarchie Up: Objekte, Klassen und Methoden Previous: Die Strategie der OOP   Contents   Index


Klassen und Methoden definieren

Die Definition einer Klasse erfolgt mit dem Schlüsselwort class:

class A
  def to_s; "ein A"; end
end
p A.new   #-> "ein A"

Innerhalb einer Klasse werden mit def Methoden festgelegt, welche die von ihr erzeugten Instanzen verwenden können. Die Methode to_s liefert einen String, der das Objekt repräsentiert. Sie wird von Ruby verwendet, wenn eine schriftliche Repräsentation des Objekts erstellt werden muss.

Um eine neue Klasse zu erzeugen, die auf einer vorhandenen Klasse aufbaut, wird folgende Syntax verwendet:

class B < A
  def to_s
    super << "bkömmling"
  end
  def to_i; 0; end
end

p B.new       #-> "ein Abkömmling"
p B.new.to_i  #-> 0
p A.new.to_i  #-> NoMethodError


\epsfig{height=36pt,file=images/chan.eps}Übrigens kann man mit den Operatoren <, >, <= und >= überprüfen, ob eine Klasse von einer anderen abgeleitet ist:

B > A  # B Oberklasse von A?   #-> false
B < A  # A Oberklasse von B?   #-> true
\epsfig{height=10pt,file=images/ruby.eps}

Mit super wird die gleichnamige Methode der Oberklasse aufgerufen. Dieser Aufruf wird vor allem dann verwendet, wenn man in einer abgeleiteten Klasse zur in der Oberklasse vorhandenen Funktionalität etwas hinzufügen möchte. Methoden, die in der Unterklasse hinzugefügt oder überschrieben werden, beeinflussen die Oberklasse nicht.

Um ein Objekt mit einer Instanzvariablen zu bestücken, reicht es, diese "`irgendwann"' zu verwenden:

class C
  def ivar; @ivar; end
  def ivar=(value); @ivar = value; end
end
c = C.new
c.ivar      #-> nil
c.ivar = 5  #-> 5
c.ivar      #-> 5


\epsfig{height=36pt,file=images/chan.eps}Es kommt oft vor, dass man der Außenwelt Zugriff auf die Instanzvariablen eines Objekts gewähren will. Wenn es reine Lese- und Schreibmethoden sind, wie im oberen Beispiel, kann man auch folgendes (zu oben gleichwertiges) Verfahren verwenden:

class C2
  attr_reader :ivar
  attr_writer :ivar
end
#oder
class C3
  attr_accessor :ivar
end

Da Klassendefinitionen in Ruby ausführbarer Code sind, muss der Interpreter Konstruktionen wie die attr-Funktionen nicht gesondert behandeln. Sie funktionieren ähnlich wie Makros in Common Lisp und sind eigentlich Methoden, die das erzeugte Class-Objekt von seiner Oberklasse Module geerbt hat.

Anhand der Implementation der attr_reader-Methode sei erklärt, wie Ruby auf Grund seiner mächtigen Reflektionsmechanismen (siehe Kapitel 17) diese Aufgabe lösen kann.

class Module\noskip
  def attr_reader(*method_symbols)
    method_symbols.each { | method |
      module_eval(
        "def #{method}; return @#{method}; end")
    }
  end
end
\epsfig{height=10pt,file=images/ruby.eps}

Gelegentlich benötigt man Klassenvariablen, die einen instanzunabhängigen Wert speichern. Solche Klassenvariablen müssen vor dem ersten Lesezugriff initialisiert werden. Im folgenden Beispiel lassen wir zählen, wie viele Instanzen einer Klasse schon erzeugt wurden. Die Methode initialize wird beim Erzeugen einer neuen Instanz automatisch aufgerufen.

class D
  @@nr = 0
  def initialize; @@nr += 1; end
  def D.status; puts @@nr; end
end
1.upto(rand 10) do D.new end
D.status

Neben Instanzmethoden, die sich an ein bestimmtes Objekt einer Klasse richten, gibt es noch Klassenmethoden, die eine Klasse als Empfänger haben. Nun sind aber Klassen in Ruby auch nur Instanzen der Klasse Class, so dass es keinen fundamentalen Unterschied zwischen Instanz- und Klassenmethoden gibt.

Um eine solche Klassenmethode zu definieren, wird in der def-Anweisung der Klassenname eingefügt. Im obigen Beispiel wird D.status unabhängig von Instanzen der Klasse aufgerufen.


next up previous contents index
Search Next: Die Klassenhierarchie Up: Objekte, Klassen und Methoden Previous: Die Strategie der OOP   Contents   Index
(C) 2002 by dpunkt.de, Armin Roehrl, Stefan Schmiedl, Clemens Wyss 2002-01-20