Zum Inhalt springen

Vala Tutorial für Java Entwickler

Warum sollte man sich für Vala interessieren?

Vala ist eine relativ junge Programmiersprache welche 2006  von den Schweizern Jürg Billeter und Raffaele Sandrini entwickelt wurde. Das besondere an Vala ist das es über moderne Features
wie z.b.  OOPLambda-Ausdrücke / Closures  Feature verfügt und dabei eine relativ leichte und verständliche Syntax beinhaltet (relativ zu Java).  Auf nervige Getter- und Setter-Methoden werden ebenso verzichtet wie auf das verkorkste Event System von Java. Vala erzeugt nativen Code mittels C, welche keine Laufzeitumgebung benötigt. Das Portieren der Vala Applikationen von Linux nach Windows ist mittels mingw leicht (Nach OSX direkt mittels gcc). Was Vala in diesem Zusammenhang auch besonders von anderen neuen Programmiersprachen wie etwa Go  hervorhebt ist, das man auf sämtliche C- Bibliotheken zugreifen kann (weiteres dazu hier) und das macht gepaart mit den oberen vorteilen, Vala aus dem Stand heraus zu einer mächtigen Programmiersprache (IMHO). Unter Linux ist eine Entwicklungsumgebung verfügbar (Anjuta DevStudio) welche “out of the box” einen ordentlichen Code Editor, sowie einen WYSIWYG GTK-Editor mit sich bringt und natürlich Vala samt compiler und co. Leider nur für Linux. Die Vala Homepage mit noch mehr Informationen finden Sie hier.

Aus Sicht eines Java Entwicklers hat es weder SUN noch Oracle geschafft Java auf dem Desktop zu etablieren. Das liegt zum einen daran das die GUI Elemente (Swing) nie wirklich in die jeweilige Oberfläche gepasst haben. Dazu kommt das Java eine VM zum ausführen benötigt, welche vor allem beim ersten Programmstart langwierig geladen werden muss. Das sind dinge die mich persönlich nicht wirklich stören, aber viele Endanwender (mit Java EE sieht es natürlich ganz anders aus).

Dieser Blog wird auch zukünftig erweitert und verbessert (z.b. Inhaltsverzeichnis). Eingereichte Beiträge z.b. über das Thema Collections sind erwünscht ebenso wie Korrekturen.

Tutorial

Dieses Tutorial wurde übersetzt und basiert größtenteils auf der englischen Originalfassung von live.gnome.org

Quelldateien

Java: *.java

Vala: *.vala


Kompilierung

Java: kompiliert nach JVM byte code (.class files)

$ javac SourceFile1.java SourceFile2.java

Vala: kompiliert nach C welcher dann z.b. mit gcc nativ übersetzt wird.

$ valac source1.vala source2.vala -o program

Vala’s standard Objekt system ist GObject, kompilierte Vala Bibliotheken sind gültig für C-Bibliotheken.

Verwenden von Bibliotheken

Java: .jar files

$ javac -classpath foo-1.0.jar;bar-3.0.jar SourceFile.java

Vala: packages (C/Vala-Bibliotheken mit .vapi files)

$ valac --pkg foo-1.0 --pkg bar-3.0 source.vala

Es sind nur  ASCII-Buchstaben für Bezeichner erlaubt. Sie können Vala Schlüsselwörter als Bezeichner verwenden, wenn sie mit dem Präfix @ beginnen. Das At-Zeichen wird nicht als Teil des Namens berücksichtigt.

Code-Organisation


Java: eine Toplevel-Klasse pro Datei,  Dateinamen gleicht  Klassennamen

Vala: eine Vala Quelldatei kann mehrere Klassen enthalten, Dateiname muss nicht der Name einer Klasse ähneln

Hierarchie

Java: packages, abgebildet in der  Verzeichnis-Hierarchie, welche das Reverse Domain Name System repräsentieren

import javax.swing.*;
package org.foo.bar;

Vala: namespaces, basiert nicht auf der Verzeichnis-Hierarchie, kein Reverse Domain Name System im Zusammenhang

using Gtk;            // importiert die Gtk Bibliothek
namespace Foo.Bar {
 // ...
}

Vala Namespaces können Methoden ohne Klassen enthalten. Sie sind implizit statisch.

Default Imports

Java: package java.lang.* default Import

Vala: namespace GLib default Import

Start Methode

Java: public static void main(String[] args)

Vala: static int main (string[] args)

Diese kann außerhalb einer Klasse und privat sein. Kann zurückkehrenden Exit-Code liefern (int),  args-Argumente sind möglich.

Basis Typen

  • grösse von  (intlong, …) welche Architektur(CPU) abhängig ist.
    Get size of a type in bytes with sizeof (), e.g. sizeof (int)
  • Zusätzliche Vala typen int8int16int32int64 (signed), uint8uint16uint32uint64 (unsigned) mit Architektur unabhängige und garantierten Größen
  • kein byte (bei uint8, stattdessen int8)
  • bool statt boolean
  • zusätzliche Basis typen: unichar repräsentieren die Unicode character

Konstante modifier: const anstatt final.

Vala’s Basis Typen haben Methoden:

int a = -4.abs ();
string s = a.to_string ();
int b = int.max (5, 7);      // statische Methoden können über 'int' aufgerufen werden.

Strings

Java

Datentype: String
Vergleichstest: str1.equals(str2)

Vala

Datentype: string (lower case)

Vergleichstest: str1 == str2

String vergleiche, vergleichen Inhalte keine  Referenzen. Man kann strings lexikographisch
vergleichen mit <><=>= etc. Strings können mit switch genutzt werden.

Vala strings sind UTF-8 encoded.

Zusätzliche  String Funktionen in Vala

Vala unterstützt “wörtliche” strings mit: """..."""
string verbatim = “””Verbatim strings berücksichtigen keine escape Sequenzen
wie \n, \t, … und kann mehrere Zeilen umfassen.Die Zeilenumbrüche sind Teil
der strings. Sie können mit Anführungszeichen(“) und backslash (\)
innerhalb eines Wörtlichen-Strings ohne abschließendes (“””) sein.

Vala unterstützt string Templates mit: @"...". String Templates können Ausdrücke enthalten
mit vorangestellten $ Zeichen.

string name = "John";
stdout.printf (@"Welcome, $name!");
stdout.printf (@"3 + 2 = $(3 + 2)");

Arrays

dynamisches erweitern

Elemente können in Arrays dynamisch erweitert werden, indem Sie den Operator += nutzen.  In Java ist dieses nicht möglich.

int[] squares = {};

for (int i = 0; i < 100; i++) {
    squares += i * i;
}

Keine Größenüberprüfung

Es gibt zur Laufzeit keine Größenprüfung für Arrays in Vala:

int[] a = new int[10];
a[20] = 1;  // Nicht sicher!
(Optionale Größenprüfung geplant.)

Multi-Dimensionale Arrays

Java: multi-dimensional arrays [][] (arrays von arrays)

int[][] matrix = new int[3][];
for (int[] row : matrix) {
    row = new int[4];
}

Vala: quadratisches multi-dimensional arrays [,][,,], usw.. (zugeordnet als ein zusammenhängender Speicherblock)

int[,] matrix = new int[3,4];

Illustration: “quadratisches vs. zerklüftetes” multi-dimensionale arrays

multidimensional-arrays.png

Type Inference (Typrückschluss)

Vala unterstützt einen Mechanismus namens type inference (Typrückschlusses (implizite Typisierung)) für lokale Variablen: Lokale Variablen können mit  dem “var” keyword statt der Typenbezeichnung begonnen werden, wenn der Compiler diese ableiten kann (infer). Dies hilft die Vermeidung unnötiger Redundanz und ist besonders nützlich für generische Typen. Beispiele:

var obj = new Object ();
var map = new HashMap<string, int> ();
var str = "hello, world";
var arr = new int[10];

Statt:

Object obj = new Object ();
HashMap<string, int> map = new HashMap<string, int> ();
string str = "hello, world";
int[] arr = new int[10];

Alles ist statisch typisiert.

Foreach

Java: for (int i : numbers) { }

Vala: foreach (int i in numbers) { }

Inheritance (Vererbung)

Java: extendsimplements

public class Demo extends Foo implements Bar {
    public Demo() {
        super();
    }
}

Vala: Doppelpunkt, gefolgt von Komma getrennte Auslistung, für Oberklassen und Schnittstellen

public class Demo : Foo, Bar {
    public Demo () {
        base ();
    }
}

super heist in Vala base.

Objekt Basis Klasse

Java: implizite Vererbung (implicit inheritance)  von Objekt (java.lang.Object)

public class Foo {
    // ...
}

Vala: keine implizite Vererbung von Objekt (GLib.Object)

public class Foo : Object {
    // ...
}

Was passiert wenn Sie nichts von einem Objekt erben? Nichts schlimmes. Diese Klassen werden etwas kleiner sein und es werden einige Funktionen wie z.B. Eigentumsänderung-Benachrichtigungen werden fehlen und Ihre Objekte werden nicht über eine gemeinsame Basisklasse verfügen. In der Regel bestimmen Sie selbst, was vom Objekt geerbt werden soll.

Methoden überladen

Java

public class Demo {

    public void draw(String text) { }

    public void draw(Shape shape) { }

    /* Methodenüberladung und Verkettung für bequemes Methoden
   /* überladen mit weniger Argumenten*/

    void f(int x, String s, double z) { }

    void f(int x, String s) {
        f(x, s, 0.5);
    }

    void f(int x) {
        f(x, "hello");
    }
}

Vala: Keine Methoden Überladung stattdessen müssen unterschiedliche Methodennamen gewählt werden.

public class Demo : Object {

    public void draw_text (string text) {
    }

    public void draw_shape (Shape shape) {
    }

    /* Method with argument default values */
    void f (int x, string s = "hello", double z = 0.5) {
    }
}

Vala unterschützt nicht das überladen von Methoden, da in Vala  geschriebene libraries  auch für C. Entwickler mit sinnvollen Funktionsnamen genutzt werden können.

Mehrere Konstruktoren

Java: constructor overloading (Konstruktor Überladung)

public class Foo {
    public Foo() { }
    public Foo(int foo) { }
    public Foo(String bar) { }
}
new Foo();
new Foo(42);
new Foo("hello");

Vala: Benannten Konstruktor statt Konstruktor Überladung.

public class Foo : Object {
    public Foo () { }
    public Foo.with_foo (int foo) { }
    public Foo.from_bar (string bar) { }
}
new Foo ();
new Foo.with_foo (42);
new Foo.from_bar ("hello");

Konstruktor Verkettung

Java: this()

class Foo {
    public Foo() {
        this("bar");
    }

    public Foo(string bar) {
    }
}

Vala: this() oder this.name_addition()

class Foo : Object {
    public Foo () {
        this.with_bar ("bar");
    }

    public Foo.with_bar (string bar) {
    }
}

Overriding (Methoden Überschreiben)

Java: Alle Methoden sind virtuell überschreibbar voreingestellt, final verhindert das überschreiben

public class Super {
    public int myMethod(int x, int y) { }
    public final void anotherMethod() { }
}

public class Sub extends Super {
    @Override
    public int myMethod(int x, int y) {
        super.myMethod(x, y);
        // ...
    }
}

Vala: Alle Methoden sind nicht-virtuelle und nicht überschreibbar. Standardmäßig muss das Überschreiben explizit zugelassen werden. Umgekehrt zu Java.Vala nutzt das Schlüsselwort  “override”
statt “@Override” und ist nicht optional.

public class Super : Object {
    public virtual int my_method (int x, int y) { }
    public void another_method () { }
}

public class Sub : Super {
    public override int my_method (int x, int y) {
        base.my_method (x, y);
        // ...
    }
}

Access Modifiers (Zugriffsmodifizierer)

Java Vala
public public
protected protected
package-private (voreingestellt) internal
private private (voreingestellt)

Obwohl private Standard ist, können Sie explizit Methoden public setzen.

Interfaces (Schnittstellen)

Java: interface Methoden sind implizit abstract

public interface Foo {
    public void foo(int i);
    public int bar(String s, double d);
}

Vala: abstract explizit notwendig

public interface Foo {
    public abstract void foo (int i);
    public abstract int bar (string s, double d);
}

Warum ist das so?  Vala-Schnittstellen können nicht-abstrakte Methoden haben (dh. Methoden mit Implementierungen). Vala Schnittstellen können gemixt (eingeschränkte Form der Mehrfachvererbung) verwendet werden. Vala-Schnittstellen können statische Methoden, z. B. Factory-Methoden beinhalten.

Vala interface können statische (static) Methoden haben, z.b.. factory Methoden.

Java: interface inheritance (Interface Vererbung)

public interface IfaceA {
    public void methodA();
}

public interface IfaceB extends IfaceA {
    public void methodB();
}

public class Demo implements IfaceB {
    public void methodA() { }
    public void methodB() { }
}

Vala: interface Voraussetzung

interface IfaceA : Object {
    public abstract void method_a ();
}

interface IfaceB : Object, IfaceA {
    public abstract void method_b ();
}

class Demo : Object, IfaceA, IfaceB {
    public void method_a () { }
    public void method_b () { }
}

Schnittstellen in Vala können nicht von anderen Schnittstellen erben, aber sie können andere Schnittstellen Voraussetzungen deklarieren, welches etwa auf gleiche Weise arbeitet. Schnittstellen können auch Klassen als Voraussetzung haben. Dies wird oft verwendet um sicherzustellen, dass eine Instanz einer Schnittstelle auch eine Objekt-Unterklasse beinhaltet. Die Tatsache das Schnittstellen nicht von anderen Schnittstellen erben können ist meist nur eine technische Unterscheidung - in der Praxis funktioniert Valaś System genauso wie Javaś in diesem Bereich, aber mit dem zusätzlichen Feature von Voraussetzten (prerequsite) Klassen.

Enums (Aufzählungen)

Java: enums sind Klassen basiert.

Vala: enums sind integer basierend. Methoden erlauben, allerdings keine Konstruktoren, Felder, usw..

enum Season {
    SPRING,
    SUMMER,
    AUTUMN,
    WINTER;

    public bool is_hot () {
        return this == SUMMER;
    }
}

Run-Time Type Information (Laufzeit Type Informationen)

Dynamische Typ überprüfung

Java: obj instanceof Foo

Vala: obj is Foo

Dynamisches Typ Casting (dynamische Typ Umwandlung)

Java: Foo foo = (obj instanceof Foo) ? (Foo) obj : null

Vala: Foo foo = obj as Foo

und natürlich, “(obj is Foo) ? (Foo) obj : null” funktioniert auch.

Getting Type Information (Type Informationen ermitteln)

Java

Class c = Foo.class;
System.out.println(c.getName());
Foo = (Foo) c.newInstance();

Vala: typeof () operator

Type t = typeof (Foo);
stdout.printf ("%s\n", t.name ());
Foo o = (Foo) Object.new (t);

Object Destruction (Objekt Zerstörung)

Java: finalisiert, nicht deterministisch

public class Foo {
    @Override
    protected void finalize() {
    }
}

Vala: destruktor, deterministisch

public class Foo : Object {
    ~Foo () {
    }
}

Annotations

Java: @Annotations, selbst definierbar

Vala: Attribute sind im Compiler eingebaut. Syntax: [AttributeName (param1 = Wert, param2 = Wert)]. Vor allem für Bindungen oder D-Bus-Schnittstellen (Desktop-Kommunikation unter Linux) verwendet. Der prominenteste Attribut für Bindungen ist [CCode (...)]

Properties

Java: Bean Konvention, getX() und setX() Methoden

public class Person {
    private int age = 32;

    public int getAge() {
        return this.age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public static void main(String[] args) {
        Person p = new Person();
        p.setAge(p.getAge() + 1);
    }
}

Vala: Sprachunterstützung für  properties (Eigenschaften), get {} und set {} blöcke, können wie auf Felder zugegriffen werden, wodurch sich das ungeliebte getter und setter verhalten verbessert.

public class Person : Object {
    private int _age = 32;

    public int age {
        get { return _age; }
        set { _age = value; }
    }
}

void main () {
    var p = new Person ();
    p.age++;
}

Oder noch kürzer für die Standard Implementation:

public class Person : Object {
    public int age { get; set; default = 32 }
}

Delegates, Closures

Java: implementiert delegierte Muster, und nutzt anonyme innere Klassen

public interface MyDelegateType {
    public void invoke(int a, double b);
}

public class Demo {
    private static void foo(MyDelegateType deleg) {
        deleg.invoke(32, 0.25);
    }

    public static void main(String[] args) {
        MyDelegateType deleg = new MyDelegateType () {
            public void invoke(int a, double b) {
                System.out.println("a = " + a + "; b = " + b);
            }
        };
        deleg.invoke(42, 0.75);
        foo(deleg);
    }
}

Vala: Vala unterstützt delegates und closures

delegate void MyDelegateType (int a, double b);

void foo (MyDelegateType deleg) {
    deleg (32, 0.25);     // invoke delegate
}

void main () {
    MyDelegateType deleg = (a, b) => {
        stdout.printf ("a = %d; b = %g\n", a, b);
    };
    deleg (42, 0.75);     // aufruf von delegate
    foo (deleg);          // übergibt delegate einer Methode
}

Closures sind anonyme Methoden welche die Variablen des äußeren Geltungsbereichs erfassen. Sie können zugewiesene Variablen  delegieren oder als delegierten Parameter an Methoden übergeben werden.

Sie können Methoden auch direkt zuweisen, um Variablen zu delegieren:

delegate int MyDelegateType (int a, double b);

int add (int a, int b) {
    return a + b;
}

int sub (int a, int b) {
    return a - b;
}

void main () {
    MyDelegateType deleg = add;
    int sum = deleg (2, 3);
    deleg = sub;
    int diff = deleg (8, 4);
}

Dies bedeutet, Methoden können in Variablen gespeichert werden und und wie Objekte übergeben werden.

Notification (Ereignis Benachrichtigung)

Java: listeners (implement observer pattern)

public interface ClickListener {
    public void clicked(Clickable source);
}
public interface Clickable {
    public void addClickListener(ClickListener l);
    public void removeClickListener(ClickListener l);
}
public class MyButton implements Clickable {
    private List<ClickListener> clickListeners;

    public MyButton() {
        this.clickListeners = new ArrayList<ClickListener>();
    }

    private void fireClickListeners() {
        for (ClickListener listener : this.clickListeners) {
            listener.clicked(this);
        }
    }

    public void addClickListener(ClickListener l) {
        if (l != null) {
            this.listeners.add(l);
        }
    }

    public void removeClickListener(ClickListener l) {
        if (l != null) {
            this.listeners.remove(l);
        }
    }

    public void test() {
        fireClickListeners();    // fire listeners
    }
}
public class Demo {

    private class MyClickListener implements ClickListener {
        public void clicked(Clickable s) {
            System.out.println("handler C");
        }
    }

    public static void main(String[] args) {
        MyButton b = new MyButton();
        b.addClickListener(new ClickListener() {
            public void clicked(Clickable s) {
                System.out.println("handler A");
            }
        });
        b.addClickListener(new ClickListener() {
            public void clicked(Clickable s) {
                System.out.println("handler B");
            }
        });
        MyClickListener handlerC = new MyClickListener();
        b.addClickListener(handlerC);
        b.test();
        b.removeClickListener(handlerC);
    }
}

Vala: Arbeitet mit signalen (signal keyword, .connect() and .disconnect()) was den
Event Code kleiner und übersichtlicher macht.

public class MyButton : Object {

    public signal void clicked ();

    public void test () {
        clicked ();          // sende signal
    }
}

void handler_c (MyButton source) {
    stdout.printf ("handler C\n")
}

void main () {
    var b = new MyButton ();
    b.clicked.connect ((s) => stdout.printf ("handler A\n"));
    b.clicked.connect ((s) => {
        stdout.printf ("handler B\n")
    });
    b.clicked.connect (handler_c);
    b.test ();
    b.clicked.disconnect (handler_c);
}

Property Änderungsbenachrichtigung

Java

import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;

public class DemoBean {

    private final PropertyChangeSupport pcs = new PropertyChangeSupport(this);
    private String title;

    public String getTitle() {
        return this.title;
    }

    public void setTitle(String title) {
        String old = this.title;
        this.title = title;
        this.pcs.firePropertyChange("title", old, title);
    }

    public void addPropertyChangeListener(PropertyChangeListener listener) {
        this.pcs.addPropertyChangeListener(listener);
    }

    public void removePropertyChangeListener(PropertyChangeListener listener) {
        this.pcs.removePropertyChangeListener(listener);
    }

    public static void main(String[] args) {
        DemoBean demo = new DemoBean();
        demo.addPropertyChangeListener(new PropertyChangeListener() {
            public void propertyChange(PropertyChangeEvent evt) {
                System.out.println("Property " + evt.getPropertyName() + " changed");
            }
        });
        demo.setTitle("hello");
        demo.setTitle("world");
    }
}

Vala: Unterklasse von Object hat ein Benachrichtigungs Signal

public class Demo : Object {
    public string title { get; set; }
}

void main () {
    var demo = new Demo ();
    demo.notify.connect ((s, p) => stdout.printf ("Property %s changed\n", p.name));
    demo.title = "hello";
    demo.title = "world";
}

Sie können jedoch nicht alte Werte ermitteln.
Wenn Sie nur an einer Änderungsbenachrichtigung einer einzigen Eigenschaft interessiert sind, können Sie die folgende Syntax verwenden:

demo.notify["title"].connect ((s, p) => stdout.printf ("title changed\n"));

Benachrichtigungen über Änderungen können mit einem CCode Attribut tag sofort deaktiviert werden:

class MyObject : Object {

    // notify signal is NOT emitted upon changes in the property
    [CCode (notify = false)]
    public int without_notification { get; set; }

    // notify signal is emitted upon changes in the property
    public int with_notification { get; set; }
}

Exceptions (Ausnahme verhalten)

Java: Klassen basierte exceptions

public class TemperatureException extends Exception {
}
public class TooColdException extends TemperatureException {
}
public class TooHotException extends TemperatureException {
}
public class ExceptionDemo {
    private void method() throws TemperatureException {
        throw new TooColdException("It's too cold!");
    }

    public static void main(String[] args) {
        try {
            method();
        } catch (TemperatureException e) {
            System.out.println(e.getMessage());
        }
    }
}

Vala: exceptions heissen errors und sind nicht Klassen basiert.

// error domain mit mehreren Fehlercodes anstelle von Exception-Klassen
errordomain TemperatureError {
TOO_HOT,
    TOO_COLD
}

void method () throws TemperatureError {
    // error domain, error code, error message
    throw new TemperatureError.TOO_COLD ("It's too cold!");
}

// muss Abgefangen oder propagiert werden, wenn Compilerwarnung ignoriert wird.
try {
    method ();
} catch (TemperatureError e) {
    stderr.printf ("Error: %s\n", e.message);
}

Obwohl der Compiler Warnungen für Fehler ignoriert, führt es nicht zum Abbruch der Kompilierung. Dies ermöglicht Prototyping.

You can check the error code with is:

    if (e is TemperatureError.TOO_COLD) {
        // ...
    }

Parameter Directions (Parameter Anweisung)

Vala Methoden haben bzw. verfügen über so genannte ref Argumente. Wenn ein Methoden Argument als out oder ref-Argument deklariert ist bedeutet, dass die Methode den Wert der übergebenen Variablen (nur Variablen können als out oder ref-argument weitergegeben werden) ändern und die Änderung auch gültig ist, nachdem die Methode zurück gegeben worden ist . Wenn die zu übergebene Variable von einem Referenz-Typ ist, kann die Methode den eigenen Verweis ändern (weist ein neues Objekt der Variablen statt nur Ändern des Zustands des übergeben Objekts zu).

Der Unterschied zwischen out und ref ist, dass eine übergebene Variable als Argument ref initialisiert werden muss, bevor sie an die Methode übergeben werden kann. Wenn eine  Variable  mit out Argument übergeben wird, muss sie nicht initialisiert werden und wird voraussichtlich erst von der Methode initialisiert werden.

Die Schlüsselwörter (out und ref) müssen sowohl bei der Definition als auch dem Methoden aufgerufen verwendet werden.

/* Die Methode benötigt ein normales Argument sowie "out" und "ref"
 */
void my_method (int a, out int b, ref int c) {
    a = 20;  // hat keine Auswirkungen außerhalb dieser Methode

    // bisher wurde "b" nicht initialisiert
    b = 30;  // Initialisierung von 'b' beeinflusst die übergebene Variable
    c = 40;  // beeinflusst die Übergebene Variable
}

void main () {
    int x = 2
    int y;         // darf ruhig nicht initialisiert sein da oben (out int b)... also out verwendet wird
    int z = 4;  // Muss initialisiert sein bevor sie als "ref" Argument übergeben wird
    my_method (x, out y, ref z);                 // out und ref müssen auch beim Aufruf deklariert werden
    stdout.printf ("%d %d %d\n", x, y, z);  // => "2 30 40"
    //"x" hat sich nicht verändert während 'y' und 'z' sich verrändert haben
}

Nullability (Null-Zulässigkeit)

In Vala können null Referenz Typen im Methoden-Kopf mit einem Fragezeichen (?) deklariert werden,
womit null Referenz Typen bei dem Methodenaufrufe gestattet werden.

void my_method (Object? a, Object b) { }

void main () {
    my_method (null, new Object());  // allowed (first argument may be null)
    my_method (null, null);          // not allowed (second argument must not be null)
}

Es wird zur Laufzeit sowie beim compilieren auf null pointer getestet.

void main () {
    string? a = "hello";
    string b = a;        // Error: 'a' darf null sein aber 'b" nicht.
}

Argument Checking

Java

void method(double d, int i, Foo foo) {
    if (d < 0 || d > 1.0)
       throw new IllegalArgumentException();
    if (i < 0 || i > 10)
        throw new IllegalArgumentException();
    if (foo == null)
        throw new IllegalArgumentException();
    // ...
}

Vala: Referenz Typparameter werden implizit auf NULL Werte überprüft, wenn sie mit “?” markiert worden sind. So müssen sie nicht manuell auf null überprüft werden.
Methoden können Vorbedingungen haben:

void method (double d, int i, Foo foo)

     requires (d >= 0.0 && d <= 1.0)
     requires (i >= 0 && i <= 10)
{
    // ...
}

Vala unterstützt zusätzlich Nachbedingungen (postconditions), z. B. zur Überprüfung des Rückgabewertes:

int square (int i)
    ensures (result >= 0)
{
    return i * i;
}

Ergebnis von return ist eine spezielle Variable, welchen den Rückgabe Wert darstellt.

Verwenden Sie Ausnahmebedingungen (errors) bei Laufzeitfehlern (Datenbank-Fehler, I/O Fehler),

Structs

Structs  ist ein Konzept welches es in  Java nicht gibt.
Beispiel:

JAVA:

class Point {

    public int x;
    public int y;

    public Point (int x, int y) {
        this.x = x;
        this.y = y;
    }

    public void print () {
        stdout.printf ("(%d, %d)", this.x, this.y);
    }
}
VALA:
struct Point {
    public int x;
    public int y;

    public Point (int x, int y) {
        this.x = x;
        this.y = y;
    }

    public void print () {
        stdout.printf ("(%d, %d)", this.x, this.y);
    }
}

Wie Sie sehen können, ist der einzige Unterschied das Schlüsselwort struct statt der Klasse. Allerdings haben struct-Typen unterschiedliche Bedeutungen als Klasse-Typen:

// Class
var p1 = new Point (2, 4);  // weist p1 dem heap zu
var p2 = p1;                // Zuweisung der Referenz
p2.x = 3;
p1.print ();                // => (3, 4)   p1 wurde ebenfalls verändert
p2.print ();                // => (3, 4)
var p3 = new Point (3, 4);
p2 == p3;                   // => false (selben Werte, aber verschiedene Referenzen)
// Struct
var p1 = Point (2, 4);      // Legt p1 auf den stack
var p2 = p1;                // kopie
p2.x = 3;
p1.print ();                // => (2, 4)   p1 ändert sich nicht
p2.print ();                // => (3, 4)
var p3 = Point (3, 4);
p2 == p3;                   // => true (gleiche Werte)
Structs werden nicht auf dem Heap gelegt . Das ist der Grund warum mit dem  new -Schlüsselwort keine Strukturen (structs) erzeugt werden. Der wichtigste Unterschied ist, dass Strukturen auf Zuweisung kopiert werden. Sie sind Werttypen, nicht Referenztypen, im Grunde verhalten sie sich wie int, double, usw.
Structs unterstützen keine Vererbung und Signale (events) und sie können keine Schnittstellen implementieren.

Synchronizing (Synchronisieren)

Java: synchronized

Vala: lock, kann nicht auf die ganze Methode angewendet werden, nur um member Objekte

Conditional Compilation (Bedingte Kompilierung)

Java: keine Bedingte Kompilierung

Vala: unterstützt #if#elif#else#endif.

siehe Conditional Compilation

Speicherverwaltung

Java: Garbage collection

Vala: Automatische Referenzzählung
weiteres: Vala’s Memory Management Explained

statische Initialisierung

Java:

public class Foo {
    static {
        System.out.println("Static initializer block invoked.");
    }
}

Vala: static construct { } block. Das erste mal wo eine Klasse oder eine Unterklasse davon instanziiert wird, wird dieser Code ausgeführt. Es wird garantiert  dass dieser Code genau einmal in einem Programm läuft in der die Klasse instanziiert wurde.

class Foo : Object {
    static construct {
        stdout.printf ("Static constructor invoked.\n");
    }
}

Additionally a Vala class can have a class construct { } block. This block will be executed once at the first use of its class, and once at the first use of each subclass of this class.

Varargs

Java:

String format(String pattern, Object... arguments) {
    // ...
}

Vala: C-style varargs, not type-safe

string format (string pattern, ...) {
    var l = va_list ();
    // ...
}

Mehr Informationen im Vala Tutorial.

Nicht verfügbar im vergleich zu Java

  • No final classes (planned as sealed classes)
  • No static classes (use nested namespaces instead)
  • No anonymous inner classes (use delegates + closures instead)
  • No constraints on generic type parameters
  • No implicit conversion of objects to strings (no general toString()). However, types that have a to_string() method are supported by string templates (@"...")
  • No named breaks / labels
  • No strictfptransient keywords

Collections

Java: java.util.* package

Vala: Gee namespace, --pkg gee-1.0http://live.gnome.org/Libgee

See Gee ExamplesGee Documentation

Vala ermöglicht Array-ähnlichen Zugriff mit hilfe der Gee Bibliothek  (zB my_map[key] ist äquivalent zu my_map.get (key)). Vala unterstützt einen Operator für Collections in: x in my_collection entspricht my_collection.contains (x). Dieser Operator funktioniert auch mit Strings, obwohl Zeichenfolgen keine Kollektions sind.

IO, Network Sockets

Java: java.io.*java.net.* packages

Vala: GLib namespace (imported by default), --pkg gio-2.0, GIO is part of GLib

See GIO ExamplesGIO Networking Examples

Console Input / Output

Java

System.out.println("Hi!");
System.out.print("Please enter your name: ");
String name = System.console().readLine();
System.out.format("Welcome, %s!\n", name);

Scanner stdin = new Scanner(System.in);
System.out.print("Enter a string, a double, a float, and an int: ");
String s = stdin.next();
double d = stdin.nextDouble();
float f = stdin.nextFloat();
int i = stdin.nextInt();

System.out.println("You entered the following:");
System.out.println("String : " + s);
System.out.println("double : " + d);
System.out.println("float  : " + f);
System.out.println("int    : " + i);

Vala

stdout.printf ("Hi!\n");
stdout.printf ("Please enter your name: ");
var name = stdin.read_line ();
stdout.printf ("Welcome, %s!\n", name);

string s;
double d;
float f;
int i;
stdout.printf ("Enter a string, a double, a float, and an int: ");
stdin.scanf ("%s", out s);
stdin.scanf ("%lf", out d);
stdin.scanf ("%f", out f);
stdin.scanf ("%d", out i);

stdout.printf ("You entered the following:\n");
stdout.printf ("string : %s\n", s);
stdout.printf ("double : %lf\n", d);
stdout.printf ("float  : %f\n", f);
stdout.printf ("int    : %d\n", i);

Von Swing to GTK+

Einfache GUI App

Java

import javax.swing.*;

public class HelloWorldFrame extends JFrame {

    public HelloWorldFrame() {
        JLabel label = new JLabel("Hello World");
        add(label);
        setSize(100, 100);
    }

    public static void main(String args[]) {
        JFrame frame = new HelloWorldFrame();
        frame.setVisible(true);
    }
}

Vala

using Gtk;

public class HelloWorldWindow : Window {

    public HelloWorldWindow () {
        var label = new Label ("Hello World");
        add (label);
        set_default_size (100, 100);
    }
}

void main (string[] args) {
    Gtk.init (ref args);

    var win = new HelloWorldWindow ();
    win.show_all ();

    Gtk.main ();
}

Must be compiled with --pkg gtk+-3.0.

See GTK+ Examples

Transition Table

Swing GTK+
JButton Button
JCheckBox CheckButton
JColorChooser ColorSelection
JComboBox ComboBox
JComponent Widget
JDialog Dialog
JEditorPane TextView
JFileChooser FileChooserDialog
JFrame Window
JLabel Label
JList TreeView with ListStore
JMenu Menu
JMenuBar MenuBar
JOptionPane MessageDialog
JPanel Container (depending on layout: BoxTableFixed, …)
JPasswordField Entry with visibility = false
JProgressBar ProgressBar
JRadioButton RadioButton
JScrollPane ScrolledWindow
JSeparator Separator
JSlider Scale
JSpinner SpinButton
JSplitPane Paned
JTabbedPane Notebook
JTable TreeView with ListStore
JTextArea TextView
JTextField Entry
JTextPane TextView
JToolBar Toolbar
JToolTip Tooltip
JTree TreeView with TreeStore
JViewport Viewport
Follow

Erhalte jeden neuen Beitrag in deinen Posteingang.