Erfolgreiche ePaper selbst erstellen
Machen Sie aus Ihren PDF Publikationen ein blätterbares Flipbook mit unserer einzigartigen Google optimierten e-Paper Software.
Abbildung 4: Wie bei Java darf die »main()«-Funktion auch Teil einer Klasse<br />
sein, sofern sie dort als »static« markiert ist.<br />
dieses Konzept als Events, Java-Programmierer<br />
nutzen Event-Listener. In Listing<br />
7 definiert die Klasse »Auto« zunächst<br />
mit dem Schlüsselwort »signal« ein neues<br />
Signal namens »anlassen«. Dieses wiederum<br />
ist nichts anderes als eine Methode<br />
ohne Rumpf.<br />
Sobald er ein Objekt der Klasse angelegt<br />
hat, kann der Programmierer mit »connect()«<br />
eine oder mehrere Methoden<br />
für das Signal registrieren. Das Listing<br />
meldet einfach nur eine anonyme Methode<br />
an. Es genügt dann der Aufruf von<br />
»anlassen()«, um das Signal auszulösen<br />
und so die anonyme Methode zu wecken.<br />
»anlassen()« verlangt dabei nach<br />
einem String, den Vala wiederum an alle<br />
registrierten Methoden weiterleitet. Im<br />
Beispiel nimmt die anonyme Methode<br />
diesen String als »a« entgegen. Zusätzlich<br />
bekommen alle registrierten Methoden<br />
immer auch das Objekt übergeben, das<br />
das Signal gesendet hat.<br />
Schreibblockade<br />
In Vala lassen sich Methoden nicht überschreiben,<br />
Entwickler dürfen folglich<br />
keine Methoden mit gleichen Namen und<br />
unterschiedlichen Parametern definieren.<br />
Bei den Konstruktoren helfen benannte<br />
Konstruktoren aus. Dabei hängt man einfach<br />
wie in Listing 8 einen Punkt mit<br />
einem Namen an.<br />
Abgeleitete Klassen dürfen die Methoden<br />
der Oberklasse sehr wohl überschreiben,<br />
im Listing zeigt dies der »Ferrari«. Der<br />
Code in der letzten Zeile ruft dann jedoch<br />
»starten()« von »Auto« auf. Das lässt sich<br />
verhindern, indem der Entwickler wie in<br />
Listing 9 die Methode<br />
der Oberklasse zu einer<br />
virtuellen macht<br />
und in der Subklasse<br />
der Methode ein<br />
»override« voranstellt.<br />
Soll die Methode in<br />
der Subklasse eine andere<br />
Signatur besitzen,<br />
stellt er ihr ein »new«<br />
voran – wie im Listing<br />
beim »BMW«.<br />
Wie C# und Java kennt<br />
Vala Interfaces. Sie geben<br />
Attribute und Methoden<br />
vor, die eine<br />
Klasse implementieren<br />
muss. Ein Beispiel zeigt Listing 10: Das<br />
»abstract« vor »starten()« weist darauf<br />
hin, dass eine Klasse die Implementierung<br />
übernimmt.<br />
Im Gegensatz zu anderen Sprachen dürfen<br />
Interfaces aber auch eine bestimmte<br />
Implementierung vorgeben (Stichwort:<br />
Mixin). Während Klassen immer nur<br />
von einer Oberklasse erben, dürfen sie<br />
beliebig viele Interfaces implementieren.<br />
Interfaces wiederum dürfen nicht von anderen<br />
Interfaces erben, wohl aber mehrere<br />
Kolleginnen und eine andere Klasse<br />
als Voraussetzung nennen. Im Beispiel<br />
gibt »Auto« die Klasse »GLib.Object« vor,<br />
von der »Ferrari« zwingend erben muss.<br />
Wechselbalg<br />
Eine Garage soll sowohl einen Ferrari als<br />
auch einen BMW aufnehmen können.<br />
Genau dafür bieten sich Generics an: Der<br />
Entwickler legt eine Klasse »Garage« an,<br />
lässt aber wie in Listing 11 den Typ der<br />
zu speichernden Daten zunächst offen.<br />
»A« dient dort als Platzhalter für einen<br />
beliebigen Datentyp. Beim Erstellen eines<br />
konkreten »Garage«-Objekts gibt er dann<br />
den jeweils gewünschten an:<br />
Garage gf = new Garage();<br />
Die neue Garage »gf« speichert damit<br />
Objekte vom Typ »Ferrari« und ist vom<br />
Typ »Garage«. Generics eignen<br />
sich vor allem für Listen und Mengen.<br />
Vala bietet in der Gee-Bibliothek ein paar<br />
häufig benötigte Datenstrukturen an, darunter<br />
etwa mit »Map« ein assoziatives<br />
Array beziehungsweise Dictionary<br />
[5]. Gee ist allerdings eine separate Bibliothek,<br />
Nutzer des fertigen Programms<br />
müssen sie folglich auf ihrem System<br />
nachinstallieren. Da sie die meisten Distributionen<br />
vorhalten, genügt ein Griff<br />
zum Paketmanager, das entsprechende<br />
Paket heißt meist »libgee«.<br />
Namenstag<br />
Mit Namespaces darf man zusammengehörenden<br />
Codeteilen einen Namen geben.<br />
Der Zugriff auf seine Klassen und<br />
Funktionen erfolgt dann über die Punktnotation:<br />
namespace Autos {<br />
class BMW { [...] }<br />
class VW { [...] }<br />
}<br />
[...]<br />
Autos.BMW meinauto = Autos.BMW();<br />
Auch die einzelnen Vala-Bibliotheken<br />
nutzen ausgiebig Namespaces. So besit-<br />
Listing 6: Alternative<br />
Klassendefinition<br />
01 public class Auto : GLib.Object {<br />
02 <br />
03 public string farbe { get; set; }<br />
04 <br />
05 public Auto(string f) {<br />
06 Object(farbe: f);<br />
07 }<br />
08 <br />
09 ~Auto() {print("verschrottet");}<br />
10 <br />
11 public void lackieren(string f) {<br />
12 this.farbe = f;<br />
13 }<br />
14 <br />
15 construct {<br />
16 print("Willkommen");<br />
17 }<br />
18 }<br />
Listing 7: Signalbehandlung<br />
01 class Auto : GLib.Object {<br />
02 public signal void anlassen(string a);<br />
03 }<br />
04 <br />
05 [...]<br />
06 <br />
07 // Signal‐Handler registrieren:<br />
08 Auto vw = new Auto();<br />
09 vw.anlassen.connect( (sender, a) => {print(a);} );<br />
10 <br />
11 vw.anlassen("Brumm"); // Signal auslösen<br />
Vala 09/2013<br />
Programmieren<br />
www.linux-magazin.de<br />
95