next up previous contents index
Search Next: Module Up: Objekte, Klassen und Methoden Previous: Ändern von Klassen   Contents   Index

Klassenvariablen und Vererbung

Eine Klassenvariable stellt einen Zugang zu einem bestimmten Objekt dar, das allen Instanzen der Klasse und ihren Unterklassen gemein ist. Wenn man diese (von Smalltalk übernommene) Eigenschaft außer Acht lässt, gerät man schnell in Verwirrung, wie das folgende Beispiel aus der Ruby-Mailingliste zeigt.

class Fahrzeug
  @@reifen = 0
  def reifen
    @@reifen
  end
end

class Auto < Fahrzeug
  @@reifen = 4
end

class Fahrrad < Fahrzeug
  @@reifen = 2
end

puts Auto.new.reifen  #-> 2  ??? Warum ???

Eine Klassenvariable ist innerhalb ihrer definierenden Klasse und deren Unterklassen global, so dass in obigem Beispiel also genau einer Variablen nacheinander drei Werte zugewiesen worden sind.

Um dieses Problem zu lösen, gibt es verschiedene Wege: Wenn sich der gespeicherte Wert nicht ändert, kann man eine klassenspezifische Konstante verwenden:

class Fahrzeug
  def reifen; type::REIFEN; end
end
class Auto < Fahrzeug; REIFEN = 4; end
class Fahrrad < Fahrzeug; REIFEN = 2; end
puts Auto.new.reifen  #-> 4

Möchte man klassenspezifische Werte speichern, die sich ändern können, bieten sich Klasseninstanzvariablen an: Ebenso wie jedes Objekt seine eigenen Instanzvariablen hat, so hat jede Klasse (Instanz der Klasse Class) ihre eigenen Klasseninstanzvariablen, die nicht mit anderen Klassen geteilt werden.

class Fahrzeug
  @reifen = 0
  def Fahrzeug.reifen  # Klassenmethode
    @reifen
  end
  def Fahrzeug.reifen=(zahl)
    @reifen = zahl
  end
end

class Auto < Fahrzeug; @reifen = 4; end
class Fahrrad < Fahrzeug; @reifen = 2; end

puts Auto.new.reifen     #-> 4
puts Fahrrad.new.reifen  #-> 2


\epsfig{height=36pt,file=images/chan.eps}Eine von Guy Decoux vorgeschlagene Lösung ist ein sehr gutes Beispiel für Ruby-typische Programmiertechniken. Sie erlaubt es, die oben manuell definierten Methoden kompakt als "`normale"' Akzessoren zu beschreiben:

class Fahrzeug
  @reifen = 0
  class << self; attr_accessor :reifen; end
end
class Auto < Fahrzeug; @reifen = 4; end
class Fahrrad < Fahrzeug; @reifen = 2; end
puts Auto.reifen, Fahrrad.reifen  #-> 4 2

Hier werden innerhalb der Klassendefinition Singleton-Methoden für die Fahrzeugklasse erzeugt, die auf die jeweils lokal gespeicherte Klasseninstanzvariable zugreifen. \epsfig{height=10pt,file=images/ruby.eps}


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