Ruby-Programmierung: Algorithmen und Datenstrukturen

Aus Wikibooks

Wechseln zu: Navigation, Suche

Zurück zu Ruby-Programmierung Hauptmenü

Inhaltsverzeichnis

[Bearbeiten] Variablen und Konstanten

Vor noch gar nicht allzulanger Zeit wurde die IT noch EDV genannt, was für elektronische Datenverarbeitung steht. Diesem interessanten Ziel wollen wir uns nun etwas nähern. Um Daten verarbeiten zu können, müssen wir sie im Arbeitsspeicher speichern können. Dies geschieht mittels sogenannter Variablen. Diese haben einen eindeutigen Namen und zeigen auf eine Stelle im Arbeitsspeicher, wo die Daten gespeichert werden. Genau genommen zeigen wir als objektorientierte Programmierer wieder auf ein Objekt, welches unsere Daten enthält, aber damit wollen wir uns ja später beschäftigen. Schauen wir uns einfach mal ein Beispiel an:

vorname = "Carl"
nachname = "Meier"
alter = 42

name = vorname + " " + nachname

puts "Hallo " + name + " (" + alter.to_s + ")"

Um einen Wert im Arbeitsspeicher zu speichern, müssen wir ihn einer Variable zuweisen, dies geschieht mit dem Gleichheitszeichen. Immer wenn der Interpreter eine Zuweisung findet, wird er das Ergebnis der rechten Seite des Gleichheitszeichen berechnen und in der Variable auf der linken Seite speichern. Bei den ersten drei Zuweisungen muss nichts berechnet werden, da wir nur einen einfachen Wert zuweisen, aber man kann auch Werte berechnen lassen.

Der Name besteht in der Regel aus Vor- und Nachname, daher überlassen wir es doch einfach dem Interpreter, den Namen aus diesen Bestandteilen zusammen zu setzen. Dazu schreiben wir einfach die Variablen, die den Wert enthalten hin und sagen mit einem +, dass die Werte verbunden werden sollen. Dann würde name aber den Wert "CarlMeier" enthalten, daher setzen wir noch einen String in die Mitte, der nur ein Leerzeichen enthält. Wir sehen also, wir können Variablen genauso verwenden wie die Werte, die sie enthalten.

Variablen heißen so, weil ihr Inhalt variabel, also änderbar sein soll. Wir können z. B. mit einer Zuweisung einer Variable einen neuen Wert geben, der vorherige verfällt dabei. Manchmal ist es aber gar nicht erwünscht, dass der Wert veränderbar ist, daher gibt es sogenannte Konstanten, die genau wie Variablen funktioneren, aber ihren Wert nach der ersten Zuweisung bis zum Ende des Scripts nicht mehr ändern.

Namen von Konstanten beginnen immer mit einem Großbuchstaben, Variablen immer mit einem kleinen. Üblicherweise schreibt man bei Konstanten auch den Rest des Namens groß, aber das ist nicht unbedingt erforderlich.

PI = 3.14159
ProgName = "Hallo Welt"

[Bearbeiten] Schlüsselwörter

Schlüsselwörter sollten nicht als Variablennamen benutzt werden, da sonst der Interpreter/Compiler eine Fehlermeldung ausgibt.

alias    and      BEGIN   begin   break    case     class    def       defined? 
do       else     elsif   END     end      ensure   false    for       if       
in       loop     module  next    nil      not      or       redo      rescue  
retry    return   self    super   then     true     undef    unless    until     
when     where    while   yield   __FILE__         __LINE__    

[Bearbeiten] Objekte

Wie in jeder objektorientierten Sprache wird in Ruby folgendes Prinzip realisiert:

  • Im Programm verwendbar sind Objekte. Sie besitzen die Eigenschaften, Daten zu speichern und Botschaften zu verstehen.
  • Jedes Objekt ist Instanz einer Klasse. Eine Klasse schreibt vor, was für Eigenschaften Objekte dieser Klasse speichern, welche Botschaften sie verstehen und wie sie auf diese Botschaften reagieren. Die Eigenschaften werden häufig als Instanzvariablen bezeichnet, Botschaften werden häufig Methoden genannt.

In Ruby herrscht folgende Besonderheit: Alles, worauf zugegriffen werden kann, ist ein Objekt; im Gegensatz zu anderen Programmiersprachen auch Zahlen oder Zeichen. Daraus folgt, dass selbst die einfachsten Elemente in Ruby Methoden besitzen; sie werden in ihren Klassen definiert.

[Bearbeiten] Methoden

Methoden werden mit dem Schlüsselwort def eingeleitet. Nach einer Parameterliste folgt der Methodenrumpf, welcher mit end abgeschlossen wird.

Beispiel:

def aneinanderhaengen(a, b)
  a.to_s + b.to_s
end

Zu beachten ist hier, dass im Gegensatz zu vielen anderen Programmiersprachen das Schlüsselwort return weggelassen werden kann. Der Rückgabewert entspricht dem Rückgabewert der zuletzt ausgeführten Anweisung. Hier: das Aneinanderhängen der String-Repräsentationen der Parameter a und b.

[Bearbeiten] Blöcke

Methodenaufrufe können zusätzlich zu Parametern noch sogenannte Blöcke entgegennehmen. Ein sehr einfaches Beispiel hierfür ist Integer#times, wobei eine Zahl den Block entsprechend ihrem Wert x-mal aufruft:

3.times { puts "Hallo" }

Ausgabe:

Hallo
Hallo
Hallo

Optional können Blöcke Parameter aufnehmen. Diese werden zwischen zwei Pipe-Zeichen geschrieben:

3.times { |i| puts "Hallo Nummer " + i.to_s }

Hallo Nummer 0
Hallo Nummer 1
Hallo Nummer 2

Bei mehreren Parametern werden diese durch Kommata abgetrennt:

ENV.each { |k,v| puts k + ' = ' + v }

_ = /usr/local/bin/irb
PATH = /bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:/usr/X11R6/bin:/usr/X11R6/sbin
DISPLAY = :0.0
SHELL = /usr/local/bin/zsh
WINDOWID = 46137348
COLORFGBG = default;default
COLORTERM = rxvt-xpm
TERM = rxvt
LC_CTYPE = en_GB.UTF-8
LANG = en_GB.UTF-8
LC_MESSAGES = en_GB.UTF-8
LC_TIME = en_GB.UTF-8

Blöcke können auch in eigenen Methoden verwendet und mit dem Schlüsselwort yield aufgerufen werden:

def tu
  yield
end
tu { puts ’Hallo’ }

Hallo

Ruft man diese Methode nun ohne Block auf, so wird ein LocalJumpError geworfen:

tu
LocalJumpError: no block given
from (irb):2:in ‘tu’
from (irb):4
from :0

Auf soetwas kann man in der Methode mit block_given? prüfen:

def tu
  yield if block_given?
end

Man kann den Block jedoch auch explizit in der Parameterliste mit einem Vorangestellten & angeben, womit man ihn auch für später beispielsweise in einer globalen Variable (vorangestelltes Dollarzeichen ($)) speichern kann:

def merke_block(&block)
  $gemerkter_block = block
end

merke_block { puts "Gemerkter Block!" }

$gemerkter_block.call
Gemerkter Block!

Wie mit $gemerkter_block.class herausgefunden werden kann, ist die Variable ein Proc-Objekt. Um eine solche zu erstellen, benötigt man gar keine Extramethode, es genügt Proc.new oder lambda. Primitiv sieht diese Funktion so aus:

def lambda(&block)
  block
end

Dies kann sehr einfach verwendet werden:

b = Proc.new { puts "Hallo" }
b.call

Hallo

[Bearbeiten] Klassen

Klassen sind in erster Linie wie in jeder objektorientierten Sprache Container für Daten mit Methoden. Variablen mit Gültigkeit für die Lebensdauer der Klasseninstanz (des Objekts) werden mit voranstehendem @ geschrieben und heissen Instanzvariablen.

Der Konstruktor ist eine ganz normale Instanzmethode und hört auf den Namen initialize:

class Drink
  def initialize(name)
    @name = name
  end
  def drink
    puts "Drinking #{@name}"
  end
end

Nun kann von der Klasse Drink ein Objekt erzeugt werden:

d = Drink.new('Juice')

Die Instanzvariable @name ist nun ein String "Juice". Auf das Objekt d, die Instanz, kann nun die Methode drink aufgerufen werden:

d.drink

Das erzeugt folgende Ausgabe:

Drinking Juice

[Bearbeiten] Vererbung

In einer objektorientierten Sprache ist natürlich auch Vererbung vorhanden:

class Mate < Drink
  def initialize
    super ’Club Mate’
  end
end

Die Klasse Mate erbt die Eigenschaften und Methoden der Klasse Drink. Dafür hat sie einen parameterlosen Konstruktor, welcher mit dem Schlüsselwort super dieselbe Methode in der Elternklasse (den Konstruktor von Drink) mit einem Parameter aufruft.

Wir können nun ebenfalls eine Instanz von Mate erstellen:

m = Mate.new
m.drink

Dies erzeugt folgende Ausgabe:

Drinking Club Mate

Bild:Wikibooks buchseite.svg Zurück zu Beispielprogramme | Bild:Wikibook.svg Hoch zu Inhaltsverzeichnis | Bild:Wikibooks buchseite.svg Vor zu Bibliotheken
Persönliche Werkzeuge