Das Tutorial ist noch im Aufbau, das bedeutet, dass noch die Kapitel noch nicht optimal aufeinander abgestimmt sind. Wir arbeiten daran. Wenn Du dieses Tutorial dennoch lesen möchtest und etwas nicht verstehst, so kannst Du im Forum Fragen stellen, aber auch gerne Kritik üben, wo Du Dinge verbessert sehen möchtest. Deine Fragen und Anregungen helfen mit, dieses Tutorial zu verbessern.
Dieses Tutorial ist nicht für Programmier-Anfänger gedacht und setzt Grundkenntnisse in objektorientierter Programmierung voraus. Es richtet sich vor allem an Programmierer, die ihre Fähigkeiten erweitern wollen und keine Angst vor Neuem haben.
Wozu brauchen wir eigentlich noch eine weitere Programmiersprache? C++, Java, C# und Co. sind doch völlig ausreichend und für alle denkbaren Gebiete einsetzbar! Auch Scriptsprachen gibt es genug: Perl und Python sind da bekannte Vertreter.
Das könnte man denken und käme mit dieser Einstellung auch wunderbar durch jeden Programmieralltag.
Zum Glück dachte einer nicht so: Yukihiro “matz” Matsumoto, der Erfinder von Ruby:
„Ich wollte eine Scriptsprache, die mächtiger als Perl und objektorientierter als Python ist.“ - Yukihiro Matsumoto |
Matsumoto stellte sich eine Scriptsprache vor, die alle positiven Eigenschaften seiner Lieblingssprachen beinhaltet. Ruby wurde also von zahlreichen Sprachen beeinflusst. Nach der offiziellen Web-Präsenz von Ruby: http://www.ruby-lang.org/de/about sind das Perl, Smalltalk, Eiffel, Ada und Lisp.
Sein Ziel war es eine Programmiersprache zu entwickeln, die natürlich ist:
„Ruby wirkt simpel, aber ist innen sehr komplex, genau wie der menschliche Körper.“ - Yukihiro Matsumoto |
Ob ihm dies gelungen ist, und ob Ruby sich unter den oben genannten Programmiersprachen etablieren kann, steht schon lange außer Frage.
Die Community spricht dieselbe eine Sprache: Ruby!
Als root:
apt-get build-dep ruby cd /opt wget ftp://ftp.ruby-lang.org/pub/ruby/1.9/ruby-1.9.2-p136.tar.gz tar xvzf ruby-1.9.2-p136.tar.gz cd ruby-1.9.2-p136 ./configure make make install
Diesen Installer herunter laden und installieren:
http://rubyforge.org/frs/download.php/73722/rubyinstaller-1.9.2-p136.exe
Ruby ist eine objektorientierte Programmiersprache, die Aspekte aus verschiedenen Programmiersprachen beinhaltet. Alles ist ein Objekt – wirklich Alles!
Es gibt keine primitiven Typen wie in Java oder C++. Auch Zahlen und Strings sind Objekte. Das bedeutet, dass man auch auf Zahlen oder Strings Methoden definieren und aufrufen kann. Das wird am besten klar, wenn man folgendes Stück Code betrachtet:
5.times { puts "Ruby is sexy" }
Dieses Code erzeugt erwartungsgemäß folgende Ausgabe:
Ruby is sexy Ruby is sexy Ruby is sexy Ruby is sexy Ruby is sexy
Objektorientierung lässt sich am besten mit Beispielen aus der Wirklichkeit verdeutlichen. Das soll hier anhand der Kaffeemaschine geschehen.
Zuerst einmal: Die Analyse
Eine Kaffeemaschine kann – natürlich – Kaffee kochen. Sie hat die Eigenschaft Wasserfüllstand, denn ohne Wasser gibt’s keinen Kaffee. Wir gehen erst einmal davon aus, dass sie an einen endlosen Vorrat von frisch gemahlenen Bohnenkaffee angeschlossen ist und uneingeschränkten Zugriff darauf hat.
Gut aufpassen, jetzt folgen die Grundlagen:
Was muss eine Kaffeemaschine können? Man kann sie einschalten, und die gewünschte Anzahl an Tassen Kaffee kochen. Entwickeln wir dazu erst folgendes HauptProgramm, so wie wir unsere Kaffeemaschine gerne bedienen würden:
Wir legen Ordner für jede Version der Kaffemaschine an. Wir starten mit dem Ordner m0.
main.rb:
require_relative 'm0/kaffee_maschine' km = KaffeeMaschine.new km.einschalten km.koche_kaffee 3
Dann bilden wir das reale Konstrukt Kaffemaschine auf eine Ruby-Klasse ab.
m0/kaffee_maschine.rb:
class KaffeeMaschine def einschalten puts "Maschine ist an" end def koche_kaffee anzahl print "Koche Kaffee" 3.times do print "." sleep 1 end puts "gekocht" anzahl.times do print "c[_] " end puts "\nWohl bekommt's!" end end
Wir starten das Programm, indem wir die Datei main.rb mit Hilfe des Ruby-Interpreters ausführen lässen:
ruby main.rb
Das Ergebnis ist:
Maschine ist an Koche Kaffe. ..gekocht c[_] c[_] c[_] Wohl bekommt's!
Klassendefinitionen werden mit dem Schlüsselwort
class
eingeleitet.
Es ist Konvention Klassennamen mit einem Großbuchstaben zu beginnen. Bei zusammengesetzten Wörter wie Kaffee und Maschine wird jeder Anfangsbuchstabe nach CamelCase-Manier groß geschrieben. Bsp.:
class KaffeeMaschine end
Um die Vererbung in Ruby zu demonstrieren soll unsere Kaffeemaschine nun eine Spezialisierung einer allgemeinen Maschine werden.
Diese allgemeine Maschine soll lediglich die Ein-/Ausschaltfunktion besitzen. Alle speziellen Maschinen sollen die Methode einschalten erben.
Dazu erstellen wir zunächst ein neues Verzeichnis m1 eine neue Klasse Maschine:
m1/maschine.rb:
class Maschine def einschalten puts "Maschine ist an" end end
Die Klasse KaffeeMaschine sieht nun entsprechend aus:
m1/kaffee_maschinen.rb:
require_relative "maschine" class KaffeeMaschine < Maschine def koche_kaffee anzahl print "Koche Kaffe" 3.times do print "." sleep 1 end puts "gekocht" anzahl.times do print "c[_] " end puts "\nWohl bekommt's!" end end
Die Datei main.rb muss leicht verändert werden:
main.rb:
require_relative 'm1/kaffee_maschine' km = KaffeeMaschine.new km.einschalten km.koche_kaffee 3
In Ruby hat jedes neu erzeugte Objekte eine eigene ID, die mit der Methode object_id heraus gefunden werden kann.
Ein Test dafür könnte so aussehen:
main.rb:
require_relative 'm1/kaffee_maschine' km = KaffeeMaschine.new puts "Object-ID: #{km.object_id}"
Die Ausgabe könnte z.B. folgendermaßen aussehen:
Object-ID: 6292400
Der Konstruktor einer Klasse heisst in Ruby initialize und wird wie eine normale Methode definiert. In unserem Beispiel könnte man ihn dazu benutzen um den Füllstand der Maschine in einer Instanzvariable @fuellstand zu speichern und mit 0 zu initialisieren.
Sagen wir, eine Tasse fasst 300ml Wasser. Also ziehen wir für jede gekochte Tasse Wasser 0.3l Wasser vom Füllstand ab. Außerdem müssen wir eine Überprüfung einbauen, die eine Fehlermeldung ausgibt, falls nicht genügend Wasser im Gerät ist.
Es wird dafür eine neue Programmversion in Ordner m2 angelegt: m2/kaffee_maschine.rb:
require_relative 'maschine' class KaffeeMaschine < Maschine def initialize @fuellstand = 0 end def koche_kaffee anzahl # Füllstandprüfung print "Ueberpruefe Fuellstand..." if @fuellstand < 0.3 * anzahl print "Bitte Wasser nachfuellen!\n" return else print "ok\n" end print "Koche Kaffee" 3.times do print "." sleep 1 end puts "gekocht" @fuellstand -= 0.3 * anzahl anzahl.times do print "c[_] " end puts "\nWohl bekommt's!" end end
Damit kommen wir zum nächsten Abschnitt: Variablen. Es gibt 4 verschiedene Arten von Variablen mit unterschiedlichen Sichtbarkeitsbereichen in Ruby:
Für jeden Variablentyp werden wie die Kaffeemaschine einen Schritt erweitern.
Um die Kaffeemaschine wartbar zu halten definieren wir das Volumen einer Tasse an einer zentralen Stelle. Zu diesem Zweck definieren wir einen globale Variable. Für jede gekochte Tasse Kaffee wird dieser Wert vom Füllstand abgezogen. Außerdem brauchen wir eine neue Methode um die Kaffeemaschine wieder mit Wasser zu befüllen.
Globale Variablen werden mit einem $ notiert.
m3/kaffee_maschine.rb:
require_relative 'maschine' $kaffee_tasse_volumen = 0.3 class KaffeeMaschine < Maschine def initialize @fuellstand = 0 end def nachfuellen anzahl print "Fuelle #{anzahl}l Wasser nach!\n" @fuellstand += anzahl end def koche_kaffee anzahl # Füllstandprüfung print "Ueberpruefe Fuellstand..." if @fuellstand < $kaffee_tasse_volumen * anzahl print "Bitte Wasser nachfuellen!\n" return else print "ok\n" end print "Koche Kaffee" 3.times do print "." sleep 1 end puts "gekocht" @fuellstand -= $kaffee_tasse_volumen * anzahl anzahl.times do print "c[_] " end puts "\nWohl bekommt's!" end end
Um die neuen Funktionen testen zu können, wird die main.rb etwas abgeändert:
main.rb:
require_relative 'm3/kaffee_maschine' km = KaffeeMaschine.new km.einschalten km.koche_kaffee 3 km.nachfuellen 1 km.koche_kaffee 3
Das sollte folgende Ausgabe erzeugen:
Maschine ist an Ueberpruefe Fuellstand...Bitte Wasser nachfuellen! Fuelle 1l Wasser nach! Ueberpruefe Fuellstand...ok Koche Kaffee...gekocht c[_] c[_] c[_] Wohl bekommt's!