next up previous contents index
Search Next: Klassenvariablen und Vererbung Up: Objekte, Klassen und Methoden Previous: Objekte und Singleton-Methoden   Contents   Index


Ändern von Klassen

Bei der Definition einer Klasse muss man sich entscheiden, wie die neue Klasse mit dem Rest des Ruby-Systems integriert werden soll. Sollen andere Ruby-Objekte als Klassen- oder Instanzvariablen eingebettet werden (Komposition)? Soll die Klasse direkt von einer anderen Klasse abgeleitet werden (Vererbung)? Letzeren Fall kann man in der LogHash-Klasse in Kapitel 14 begutachten.

Bei der direkten Ableitung müssen nur die Methoden neu definiert werden, die eine Erweiterung oder Änderung des Verhaltens der vorhandenen Klasse erfordern. Um eine schon vorhandene Methode der Oberklasse aufzurufen, verwendet man super mit den entsprechenden Argumenten.

class Punkt3d
  attr_reader :x, :y, :z, :name
  @@typ = "Punkt"
  def initialize(name, x, y, z)
    @x = x
    @y = y
    @z = z
    @name = name
  end
  def to_s
    "%s(%6.2f/%6.2f/%6.2f)" % [@name, @x, @y, @z]
  end
end

class Punkt2d < Punkt3d
  def initialize(name, x, y)
    super(name, x, y, 0)
  end
  def to_s
    "%s(%6.2f/%6.2f)" % [@name, @x, @y]
  end
end

class Strecke
  attr_reader :a, :b, :name
  @@typ = "Strecke"
  def initialize(name, a, b)
    @name = name
    @a = a
    @b = b
  end
  def to_s
    "%s[%s/%s]" % [@name, @a, @b]
  end
end

p = Punkt2d.new("P", 1, 1)
q = Punkt2d.new("Q", 2, 3)
puts s = Strecke.new("s", p, q)
  #-> s[P(  1.00/  1.00)/Q(  2.00/  3.00)]

Das erneute Definieren einer Klasse wird als inkrementelle Änderung aufgefasst, so dass eigene Methoden jederzeit hinzugefügt, aber auch überschrieben - d.h. neu definiert - werden können.

Der erste Vergleich im folgenden Beispiel verwendet die von der Object-Klasse ererbte Methode ==, mit der Objektidentität geprüft wird. Nach Erweiterung der Klasse Punkt3d wird eine geometrische Interpretation der Gleichheit verwendet, so dass gleiche Koordinaten für die Gleichheit der Punkte ausreichen.

puts p == Punkt2d.new("P", 1, 1)  #-> false

class Punkt3d
  def == (p)
    x == p.x and y == p.y and z == p.z
  end
end

puts p == Punkt2d.new("P", 1, 1)  #-> true

Im Gegensatz zu Java sind auch die eingebauten Ruby-Klassen nicht "`final"', also unveränderbar, sondern können bei Bedarf angepasst werden.


\epsfig{height=36pt,file=images/chan.eps}Bei Bedarf kann man eine Klasse mit freeze fixieren, so dass keine Änderungen mehr vorgenommen werden können. Jedoch wird beim Duplizieren mit dup stets eine nicht eingefrorene Kopie erzeugt, so dass man immer eine modifizierbare Klasse erhalten kann.

class Foo
  def to_s; "Foo"; end
end
Foo.freeze
Foo.new   #-> Foo

# Änderung der Klasse ist nicht möglich
class Foo
  def to_s; "Bar"; end #-> TypeError
end

# die Kopie ist wieder wandelbar
MyFoo = Foo.dup
class MyFoo
  def to_s; "Bar"; end
end
MyFoo.new  #-> Bar
\epsfig{height=10pt,file=images/ruby.eps}

Erweiterungen sind auch bei eingebauten Klassen möglich. Es wäre praktisch, wenn ein Array zählen könnte, wie oft es ein bestimmtes Objekt enthält. Dafür muss man nicht viel unternehmen:

class Array
  def zaehle(x)
    (select { |i| i == x }).size
  end
end

a = [1, 2, 3, 4, 5, 6, 5, 4, 3, 2, 1, 2, 3]
a.zaehle 2     #-> 3
a.zaehle 88    #-> 0


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