Aus Linux-Magazin 09/2013

Vala, eine Programmiersprache für Gnome- und GTK+-Anwendungen

© Andriy Popov, 123RF.com

Wer Programme mit GTK+ oder für Gnome schreibt, greift dabei meist zu C oder Python. Mit Vala gibt es jedoch eine interessante objektorientierte Alternative. Deren Zauber liegt in sprachlichen Anleihen bei C# und Java sowie in der Integration der Glib-Bibliothek.

2006 begann der Informatikstudent Jürg Billeter eine neue Programmiersprache zu entwickeln. Als Ausgangspunkt wählte er die Gobject-Bibliothek. Diese soll es eigentlich C-Entwicklern ermöglichen, objektorientiert zu programmieren. Das GUI-Toolkit GTK+ und viele Gnome-Bibliotheken nutzen Gobject. Jürg Billeter verrührte die Konzepte von Gobject mit C# und Java und taufte das Ergebnis Vala [1]. Da Gobject ein Teil der Glib ist, bekommen Vala-Programmierer diese als Standardbibliothek gratis ins Haus. Auf Wunsch kümmert sich Vala sogar um die Speicherverwaltung.

Bindungswillig

Die Entwicklung von Vala ist noch nicht vollständig abgeschlossen, zum Redaktionsschluss war Version 0.20.1 aktuell. Die Sprachsyntax ist jedoch recht stabil: Seit Mitte 2011 hat es nur kleinere Optimierungen, Fehlerkorrekturen im Compiler sowie Anbindungen an weitere Gnome-Bibliotheken [2] gegeben. Die Alltagstauglichkeit der Sprache beweisen zahlreiche in Vala geschriebene Anwendungen, darunter die Fotoverwaltung Shotwell (Abbildung 1, [3]) und der E-Mail-Client Geary [4].

Abbildung 1: Alltagstauglich: Die Bilderverwaltungsoftware Shotwell ist in Vala programmiert.

Abbildung 1: Alltagstauglich: Die Bilderverwaltungsoftware Shotwell ist in Vala programmiert.

Vala-Programme übersetzt ein Compiler in C-Quellcode, den dann wiederum ein C-Compiler zu einer ausführbaren Binärdatei verarbeitet (Abbildung 2). Das hat den Vorteil, dass Vala-Programme ähnlich schnell wie C-Programme ablaufen und sich zudem auf allen Plattformen übersetzen lassen, auf denen C-Compiler und Glib-Bibliothek bereitstehen.

Abbildung 2: Der Vala-Compiler »valac« ruft automatisch den C-Compiler auf, der nicht nur das fertige Programm erstellt, sondern auch für die Warnmeldung verantwortlich ist.

Abbildung 2: Der Vala-Compiler »valac« ruft automatisch den C-Compiler auf, der nicht nur das fertige Programm erstellt, sondern auch für die Warnmeldung verantwortlich ist.

Darüber hinaus kann der Programmierer in Vala alle vorhandenen C-Bibliotheken nutzen und umgekehrt in Vala geschriebenen Programmcode in anderen C-Programmen einsetzen. Bindungen existieren bereits zu zahlreichen Gnome-Bibliotheken, Benutzeroberflächen beispielsweise entstehen wie bei Shotwell und Geary häufig mittels GTK+.

Hallo Vala!

Ein Hallo-Welt-Programm zeigt Listing 1. Bei seinem Start ruft Vala automatisch die »main()« -Funktion auf. In ihr legt das Listing die Variable »hallo« an, die eine Zeichenkette (»string« ) speichert und den Text »Hallo Welt!\n« aufnimmt. Vala versteht die üblichen Escape-Zeichen, »\n« steht im Beispiel für einen Zeilenumbruch. Die Funktion »print()« bringt den Text in der Variablen »hallo« auf den Bildschirm. Abschließend gibt »return« eine »0« zurück, womit das Programm den fehlerfreien Ablauf bestätigt. Jede Anweisung schließt mit einem Semikolon ab.

Listing 1

Hallo Welt!

01 // Dies ist ein Kommentar ...
02 /* ... und dies auch */
03 int main() {
04         string hallo = "Hallo Welt!\n";
05         print(hallo);
06         return 0;
07 }

Typsache

Von C# und Java geerbt hat Vala die Kontrollstrukturen (»if« , »while« , »for« ), die Vergleichsoperatoren (wie »==« und »!=« ) sowie die Datentypen (etwa »int« und »bool« ). Wie in C besitzen die meisten Datentypen allerdings auf verschiedenen Plattformen unterschiedliche Größen. Für Integerwerte – und nur für sie – gibt es deshalb auch Datentypen mit einer garantierten Größe. So repräsentiert »int32« immer eine 32-Bit-Zahl. Soll Vala den Typ einer Variablen selbst ermitteln (Typinferenz), deklariert man sie als »var« :

var zahl = 1;

Strings nutzen immer die UTF-8-Zeichenkodierung und sind unveränderbar. Der nützliche »in« -Operator ergibt einen wahren Ausdruck, wenn eine Zeichenkette in einer anderen enthalten ist:

if ("rote" in "Das rote Auto") { [...]

Um berechnete Werte in einen String einzusetzen, muss der Programmierer wie in Abbildung 3 nur die Variable hineinschreiben, ihr ein »$« voranstellen und vor dem String ein »@« notieren. Das »$« zeigt Vala an, dass es einen Ausdruck auswerten soll. In der Abbildung ersetzt es folglich nicht nur »$a« und »$b« durch die Variableninhalte, sondern rechnet auch »a+b« aus.

Abbildung 3: Über den »+=«-Operator lassen sich an Strings weitere Zeichen anhängen (wie hier der Zeilenumbruch).

Abbildung 3: Über den »+=«-Operator lassen sich an Strings weitere Zeichen anhängen (wie hier der Zeilenumbruch).

Eckig geklammert

Mittels eckiger Klammern und Positionsangaben greift der Programmierer auf Substrings zu, in Abbildung 3 enthält »ergebnis« damit die Zeichen »42« . Auf diese Weise lassen sich auch Arrays teilen, die man in Vala explizit mit »new« anlegen muss. In Listing 2 entsteht ein Array mit drei Elementen, Zeile 2 erstellt ein zweidimensionales Array mit drei mal vier Elementen, Zeile 5 weist dem Array »e« seine Werte direkt zu. Liegt in Vala ein Array vor, kann der Entwickler die besonders lesefreundliche »foreach« -Schleife nutzen. So gibt

Listing 2

Arrays

01 int[] c = new int[3];
02 int[,] d = new int[3,4];
03 c[1] = 99;
04 d[1,3] = 88;
05 int[] e = {1,2,3};
foreach(string z in zahlen) {print(z);}

alle Elemente des Array »zahlen« aus:

Mit Methode

Funktionen heißen in Vala Methoden, es sind C-Funktionen. Sie können daher immer nur einen einzigen Wert zurückliefern. Ihre Argumente darf der Programmierer mit Standardwerten vorbelegen, zum Beispiel:

int addiere(int x, int y = 1) { [...] }

Hinter der Bezeichnung Delegates verbergen sich spezielle Methoden, die sich in Variablen speichern oder an andere Methoden übergeben lassen. Listing 3 zeigt dazu ein Beispiel: In Zeile 3 legt zunächst das Schlüsselwort »delegate« einen neuen Datentyp namens »RechneTyp« an. Dieser repräsentiert ab sofort eine Methode, die einen Integerwert entgegennimmt und auch einen solchen zurückliefert. Anschließend kann der Programmierer eine Variable dieses Typs anlegen (»RechneTyp a;« ). In ihr lässt sich eine Funktion speichern, die exakt der Signatur von »RechneTyp« entspricht.

Listing 3

Delegates

01 int addiere(int x) { return x+x; }
02
03 delegate int RechneTyp(int x);
04
05 int machwas(RechneTyp r, int zahl) {
06         return r(zahl);       // Aufruf des Delegate
07 }
08
09 int main() {
10
11         // Aufruf über Variable:
12         RechneTyp a;
13         a = addiere;
14         int ergebnis = a(5);
15
16         // Direkter Aufruf der Methode:
17         int ergebnis2 = machwas(addiere, 2);
18
19         return 0;
20 }

In Listing 3 trifft das auf die Methode »addiere()« zu. Die in der Variablen gespeicherte Funktion (»a = addiere;« ) lässt sich dann aufrufen: »a(5)« . Ebenfalls in diesem Listing zeigt die Funktion »machwas()« schließlich noch, wie man einer Methode eine Kollegin übergibt. Wer »addiere()« nur an einer einzigen Stelle benötigt, kann sogar auf ihren Namen verzichten und ihren Rumpf direkt einer Variablen zuweisen:

RechneTyp a = (x) => {return x+x;};
int b = a(3);

Hier speichert die Variable »a« eine namenlose Methode, die ein Argument »x« besitzt und mit diesem »x+x« berechnet. Vala bezeichnet solche Funktionen als anonyme Methoden, andere Sprachen sprechen von einem Lambda-Ausdruck. In Vala haben anonyme Methoden sogar Zugriff auf die Variablen in ihrer direkten Umgebung, was einer Closure oder einem Funktionsabschluss entspricht:

int c = 3;
RechneTyp d = (x) => {return x+c;};
int e = d(5); // e ist hier 8

Methodenaufrufe darf der Vala-Programmierer an beliebig viele Bedingungen knüpfen (Contract Programming). Die Bedingungen für die Eingabewerte definiert »requires« , »ensures« legt jene für die Rückgabewerte fest, wobei »result« für den Rückgabewert steht:

int addiere(int x, int y)
        requires(x > 0 && y < 10)
        ensures(result > 0)
{
        return x+y;
}

Listing 4 erstellt eine neue Klasse namens »Auto« , die von der Gobject-Basisklasse »GLib.Object« erbt. »Auto« besitzt ein privates Attribut »farbe« , das sich mit der öffentliche Methode »lackieren()« ändern lässt. »this« bezeichnet das aktuelle Objekt, wie in anderen Sprachen auch.

Listing 4

Klassendefinition

01 public class Auto : GLib.Object {
02         private string farbe;
03
04         // Konstruktor:
05         public Auto(string f) {
06                 base();
07                 this.farbe = f;
08         }
09
10         // Methode:
11         public void lackieren(string f) {
12                 this.farbe = f;
13         }
14
15         // Destruktor:
16         ~Auto() {print("verschrottet");}
17 }

Neben »public« und »private« kennt Vala zwei weitere Zugriffsmodifizierer: Während bei »private« der Zugriff nur der Klasse selbst gestattet ist, dürfen bei »protected« auch alle abgeleiteten Klassen auf das Attribut oder die Methode zugreifen. »internal« wiederum gestattet allen Klassen den Zugriff, die sich in derselben Quellcode-Datei befinden.

Um eine Klasse außerhalb der aktuellen Quellcode-Datei nutzen zu können, muss der Programmierer sie wie in Listing 4 als »public« kennzeichnen. Standardmäßig sind Klassen nur »internal« . Ein neues »Auto« erstellt die folgende Zeile:

Auto bmw = new Auto("blau");

Dabei ruft Vala den Konstruktor auf, der den gleichen Namen trägt wie die Klasse. Den Konstruktor der Oberklasse aktiviert »base()« . Erlaubt ist auch ein Destruktor, den Vala aufruft, bevor es das Objekt zerstört. Destruktoren tragen den Namen der Klasse mit vorangestellter Tilde »~« . Sie sind besonders dann nützlich, wenn man selbst die Speicherverwaltung übernimmt, C-Bibliotheken nutzt oder die Klasse Ressourcen verwalten lässt.Genau wie bei Java darf auch in Vala die »main()« -Funktion Teil einer Klasse sein (Abbildung 4).

Abbildung 4: Wie bei Java darf die »main()«-Funktion auch Teil einer Klasse sein, sofern sie dort als »static« markiert ist.

Abbildung 4: Wie bei Java darf die »main()«-Funktion auch Teil einer Klasse sein, sofern sie dort als »static« markiert ist.

Eigenschaften

Private Attribute manipuliert der Entwickler in der Regel über passende »get()« – und »set()« -Methoden. Die damit einhergehende Tipparbeit reduzieren so genannte Properties. Listing 5 erstellt eine Property mit dem Namen »aussehen« , sie lässt sich wie ein öffentliches Attribut nutzen. Zeile 13 legt in ihr etwa den String »blau« ab. Vala ruft dabei im Hintergrund automatisch die »set()« -Methode der Property auf, die im Beispiel den Wert im privaten Attribut »farbe« speichert. »value« ist ein Schlüsselwort und steht für den übergebenen Wert. Wer in »get()« und »set()« nur Werte setzt beziehungsweise liest, kann sich die Variable »farbe« sogar sparen:

Listing 5

Properties

01 class Auto {
02         private string farbe = "rot";
03
04         public string aussehen {
05                 get { return farbe; }
06                 set { farbe = value; }
07         }
08 }
09
10 int main() {
11
12 Auto ferrari = new Auto();
13 ferrari.aussehen = "blau";
14 print(ferrari.aussehen);
15
16 return 0;}
public string aussehen { get; set;default = "rot";}

Sofern eine Klasse von »GLib.Object« erbt, darf man sie auch wie in Listing 6 definieren. Den abschließenden »construct« -Block führt Vala immer aus, wenn sie ein Objekt der Klasse erzeugt. Im Konstruktor weist »Object(farbe: f);« dem Attribut »farbe« den Wert aus dem übergebenen Parameter »f« zu. Mehrere Zuweisungen trennt ein Komma: »Object(farbe: f, geschwindigkeit: kmh);« . Diese Notation funktioniert jedoch nur, wenn »f« und »kmh« Properties sind.

Listing 6

Alternative Klassendefinition

01 public class Auto : GLib.Object {
02
03         public string farbe { get; set; }
04
05         public Auto(string f) {
06                 Object(farbe: f);
07         }
08
09         ~Auto() {print("verschrottet");}
10
11         public void lackieren(string f) {
12                 this.farbe = f;
13         }
14
15         construct {
16                 print("Willkommen");
17         }
18 }

Wink mit dem Zaunpfahl

»GLib.Object« bringt zudem Signalbehandlung ins Spiel: Löst ein Objekt ein Signal aus, ruft Vala automatisch alle Methoden auf, die sich für das Signal interessieren. C#-Programmierer kennen dieses Konzept als Events, Java-Programmierer nutzen Event-Listener. In Listing 7 definiert die Klasse »Auto« zunächst mit dem Schlüsselwort »signal« ein neues Signal namens »anlassen« . Dieses wiederum ist nichts anderes als eine Methode ohne Rumpf.

Listing 7

Signalbehandlung

01 class Auto : GLib.Object {
02         public signal void anlassen(string a);
03 }
04
05 [...]
06
07 // Signal-Handler registrieren:
08 Auto vw = new Auto();
09 vw.anlassen.connect( (sender, a) => {print(a);} );
10
11 vw.anlassen("Brumm"); // Signal auslösen

Sobald er ein Objekt der Klasse angelegt hat, kann der Programmierer mit »connect()« eine oder mehrere Methoden für das Signal registrieren. Das Listing meldet einfach nur eine anonyme Methode an. Es genügt dann der Aufruf von »anlassen()« , um das Signal auszulösen und so die anonyme Methode zu wecken. »anlassen()« verlangt dabei nach einem String, den Vala wiederum an alle registrierten Methoden weiterleitet. Im Beispiel nimmt die anonyme Methode diesen String als »a« entgegen. Zusätzlich bekommen alle registrierten Methoden immer auch das Objekt übergeben, das das Signal gesendet hat.

Schreibblockade

In Vala lassen sich Methoden nicht überschreiben, Entwickler dürfen folglich keine Methoden mit gleichen Namen und unterschiedlichen Parametern definieren. Bei den Konstruktoren helfen benannte Konstruktoren aus. Dabei hängt man einfach wie in Listing 8 einen Punkt mit einem Namen an.

Listing 8

Überschreiben

01 public class Auto : GLib.Object {
02         private string farbe;
03
04         public Auto() {farbe = "rot";}
05         public Auto.faerben(string f) {farbe = f;}
06
07         public void starten() {print("tucker");}
08 }
09
10 public class Ferrari : Auto {
11         public void starten() {print("brumm");}
12 }
13
14 [...]
15
16 Auto bmw = new Auto.faerben("blau");
17
18 Ferrari f = new Ferrari();
19 Auto a = f;
20 a.starten();

Abgeleitete Klassen dürfen die Methoden der Oberklasse sehr wohl überschreiben, im Listing zeigt dies der »Ferrari« . Der Code in der letzten Zeile ruft dann jedoch »starten()« von »Auto« auf. Das lässt sich verhindern, indem der Entwickler wie in Listing 9 die Methode der Oberklasse zu einer virtuellen macht und in der Subklasse der Methode ein »override« voranstellt. Soll die Methode in der Subklasse eine andere Signatur besitzen, stellt er ihr ein »new« voran – wie im Listing beim »BMW« .

Listing 9

Virtuelle Methoden

01 // Virtuelle Methoden:
02 public class Auto : GLib.Object {
03         public virtual void starten() {print("tucker");}
04 }
05
06 public class Ferrari : Auto {
07         public override void starten() {print("brumm");}
08 }
09
10 public class BMW : Auto {
11         public new void starten(string ton) {print(ton);}
12 }
13
14 [...]
15
16 BMW b = new BMW();
17 b.starten("brumm");

Wie C# und Java kennt Vala Interfaces. Sie geben Attribute und Methoden vor, die eine Klasse implementieren muss. Ein Beispiel zeigt Listing 10: Das »abstract« vor »starten()« weist darauf hin, dass eine Klasse die Implementierung übernimmt.

Listing 10

Interfaces

01 public interface Auto : GLib.Object {
02         public abstract void starten();
03 }
04
05 public class Ferrari : GLib.Object, Auto {
06         public void starten() { print("brumm\n"); }
07 }
08
09 [...]
10
11 Ferrari f = new Ferrari();
12 Auto meins = f;
13 meins.starten();

Im Gegensatz zu anderen Sprachen dürfen Interfaces aber auch eine bestimmte Implementierung vorgeben (Stichwort: Mixin). Während Klassen immer nur von einer Oberklasse erben, dürfen sie beliebig viele Interfaces implementieren. Interfaces wiederum dürfen nicht von anderen Interfaces erben, wohl aber mehrere Kolleginnen und eine andere Klasse als Voraussetzung nennen. Im Beispiel gibt »Auto« die Klasse »GLib.Object« vor, von der »Ferrari« zwingend erben muss.

Wechselbalg

Eine Garage soll sowohl einen Ferrari als auch einen BMW aufnehmen können. Genau dafür bieten sich Generics an: Der Entwickler legt eine Klasse »Garage« an, lässt aber wie in Listing 11 den Typ der zu speichernden Daten zunächst offen. »A« dient dort als Platzhalter für einen beliebigen Datentyp. Beim Erstellen eines konkreten »Garage« -Objekts gibt er dann den jeweils gewünschten an:

Listing 11

Generics

01 public class Garage<A> : GLib.Object {
02     private A wagen;
03
04     public void parke(A auto) {
05         this.wagen = auto;
06     }
07 }
Garage<Ferrari> gf = new Garage<Ferrari>();

Die neue Garage »gf« speichert damit Objekte vom Typ »Ferrari« und ist vom Typ »Garage<Ferrari>« . Generics eignen sich vor allem für Listen und Mengen. Vala bietet in der Gee-Bibliothek ein paar häufig benötigte Datenstrukturen an, darunter etwa mit »Map<G>« ein assoziatives Array beziehungsweise Dictionary [5]. Gee ist allerdings eine separate Bibliothek, Nutzer des fertigen Programms müssen sie folglich auf ihrem System nachinstallieren. Da sie die meisten Distributionen vorhalten, genügt ein Griff zum Paketmanager, das entsprechende Paket heißt meist »libgee« .

Namenstag

Mit Namespaces darf man zusammengehörenden Codeteilen einen Namen geben. Der Zugriff auf seine Klassen und Funktionen erfolgt dann über die Punktnotation:

namespace Autos {
        class BMW { [...] }
        class VW { [...] }
}[...]
Autos.BMW meinauto = Autos.BMW();

Auch die einzelnen Vala-Bibliotheken nutzen ausgiebig Namespaces. So besitzen alle Klassen aus der GTK-Bibliothek das Präfix »Gtk« , ein Fenster heißt folglich »Gtk.Window« . Wer die Schreibarbeit umgehen möchte, importiert mit »using« einen Namespace und lässt ihn in den folgenden Zeilen weg:

using Autos;
BMW meinauto = BMW();

Standardmäßig importiert Vala den Namespace »GLib« . Damit stehen alle Objekte und Methoden der Glib-Bibliothek direkt bereit. Dazu gehört übrigens auch die Methode »print()« , die man eigentlich korrekt mit »GLib.print();« aufrufen müsste.

Zeig her!

Wenn der Entwickler ein Objekt anlegt, liefert Vala nur eine Referenz darauf zurück. Bei einer Zuweisung »b = a;« liegt in »b« eine weitere Referenz auf das gleiche Objekt. Mit dem Schlüsselwort »owned« lässt sich der Besitzer wechseln:

Foo foo = (owned) bar;

Nach dieser Anweisung hat »bar« den Wert »null« , während »foo« auf das Objekt zeigt, das in »bar« war. Des Weiteren führt Vala im Hintergrund automatisch Buch darüber, wie viele Referenzen auf ein Objekt zeigen. Sobald es keine Referenzen mehr gibt, fliegt das entsprechende Objekt aus dem Speicher (Referenzzählung).

Wenn sich allerdings zwei Objekte gegenseitig nutzen, sonst aber keine weiteren Referenzen auf die beiden existieren, sind sie zwar überflüssig, ihre Zähler stehen aber dennoch nicht auf Null. Folglich bleiben die beiden Objekte für immer im Speicher. Sieht ein Programmierer solch eine Situation kommen, sollte er Vala mit dem Schlüsselwort »weak« darauf hinweisen:

class Seite {
    public weak Seite vorherige;
    public Seite naechste;
}

Wer das Speichermanagement vollkommen selbst übernehmen möchte, kann die aus C bekannten Zeiger mit der Pfeil- und Sternchennotation nutzen:

Auto* bmw = new Auto();
bmw->starte();
delete bmw;

Neben den vorgestellten Sprachelementen kennt Vala zahlreiche weitere. So gibt es unter anderem Annotationen, abstrakte Klassen sowie die aus C++ bekannten »struct« und »enum« . Zur Laufzeit lässt sich der Typ eines Objekts prüfen, während Assertions die Einhaltung vorgegebener Bedingungen sicherstellen. Vala selbst bietet jedoch keine Unterstützung für nebenläufige Verarbeitung, Threads lassen sich nur mit Hilfe der Glib-Bibliothek und deren Klasse »Thread« erstellen.

Übersetzungsdienst

Die Referenzimplementierung des Vala-Compilers steht unter der LGPL 2.1 und ist in den Repositories der meisten großen Distributionen enthalten. Bei der Installation sollten Interessenten darauf achten, möglichst die neueste Fassung zu nutzen. Wer bei der Frische auf Nummer sicher gehen möchte, schnappt sich das Quellcode-Archiv aus dem Vala-Wiki [1]. Für die Übersetzung benötigt er den C-Compiler, »make« , »flex« , »bison« sowie die Entwicklerpakete für Glib 2.0 und Gobject 2.0 (unter Ubuntu im Paket »libglib2.0-dev« ). Die Übersetzung erfolgt dann mit dem bekannten Dreisprung »./configure; make; sudo make install« . Ein »sudo ldconfig« richtet die Bibliothek »libvala« ein.

Vala-Quellcode liegt gewöhnlich in einer Textdatei mit der Endung ».vala« . Diese bekommt der Vala-Compiler mit »valac hallowelt.vala« vorgesetzt, der daraus ein Programm erzeugt – im Beispiel namens »hallowelt« . Wer am produzierten C-Code interessiert ist, lässt diesen mit »-c« erzeugen:

valac -c hallowelt.vala

Vala-Bibliotheken, etwa »libgee.so« , sind immer auch C-Bibliotheken. Um sie nutzen zu können, benötigt der Vala-Compiler ein paar Zusatzinformationen in einer so genannten VAPI-Datei. Sie verrät, welche Funktionen die C-Bibliothek bereitstellt. Für die meisten Gnome-Bibliotheken haben die Vala-Entwickler bereits passende VAPI-Dateien erzeugt. Ausführliche Informationen hierzu liefert das Vala-Wiki [1].

Die Dokumentation ist Valas größte Baustelle. Als einzige offizielle Quelle ist das Wiki noch lückenhaft, unvollständig und teilweise veraltet. Einsteigern sei dennoch das (lange) Tutorial empfohlen [6]. Für Umsteiger von C# und Java stehen gesonderte Hinweise bereit ([7], [8]).

Status quo

Vala selbst versucht C# und Java mit Gobject zu verheiraten. Dabei gelten allerdings viele kleine Ausnahmen, die der Programmierer im Hinterkopf behalten muss. Darüber hinaus besitzt Vala keine richtige Garbage Collection, sondern nur eine einfache Referenzzählung. Wer verhindern will, dass der Speicher überläuft, muss folglich die Referenzen genau im Auge behalten.

Häufig führen in Vala gleich mehrere Wege zum Ziel, etwa bei der Definition von Klassen. In der Praxis stiftet das besonders dann Verwirrung, wenn man Code von verschiedenen Entwicklern lesen muss. Unter dem Strich bietet sich Vala vor allem für Umsteiger von C# oder Java an, die möglichst flott ablaufende Programme für GTK+ oder Gnome produzieren möchten, aber die Arbeit mit C scheuen. (mhu)

DIESEN ARTIKEL ALS PDF KAUFEN
EXPRESS-KAUF ALS PDFUmfang: 6 HeftseitenPreis €0,99
(inkl. 19% MwSt.)
LINUX-MAGAZIN KAUFEN
EINZELNE AUSGABE Print-Ausgaben Digitale Ausgaben
ABONNEMENTS Print-Abos Digitales Abo
TABLET & SMARTPHONE APPS Readly Logo
E-Mail Benachrichtigung
Benachrichtige mich zu:
0 Kommentare
Älteste
Neuste Beste Bewertung
Inline Feedbacks
Alle Kommentare anzeigen
Nach oben