Vala for Java Programmers

Vala for Java Programmers

Contents

  1. Vala for Java Programmers
    1. Source Files
    2. Compilation
    3. Using Libraries
    4. Naming Conventions
    5. Code Organization
    6. Main Entry Point
    7. Basic Types
    8. Strings
    9. Arrays
    10. Type Inference
    11. Foreach
    12. Inheritance
    13. Object Base Class
    14. Method Overloading
    15. Multiple Constructors
    16. Constructor Chaining
    17. Overriding
    18. Access Modifiers
    19. Interfaces
    20. Enums
    21. Run-Time Type Information
    22. Object Destruction
    23. Annotations
    24. Properties
    25. Delegates, Closures
    26. Notification
    27. Property Change Notification
    28. Exceptions
    29. Parameter Directions
    30. Nullability
    31. Argument Checking
    32. Structs
    33. Synchronizing
    34. Conditional Compilation
    35. Memory Management
    36. Static Initialization
    37. Varargs
    38. Native Methods
    39. Not Available
    40. Features Not Covered In This Tutorial
    41. Collections
    42. IO, Network Sockets
    43. Console Input / Output
    44. From Swing to GTK+
      1. Simple GUI App
      2. Transition Table

Source Files

Java: *.java

Vala: *.vala

Compilation

Java: compiled to JVM byte code (.class files)

$ javac SourceFile1.java SourceFile2.java

Vala: compiled to native code via C code as intermediate code

$ valac source1.vala source2.vala -o program

Vala's standard object system is GObject, compiled Vala libraries are valid C libraries.

Using Libraries

Java: .jar files

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

Vala: packages (C libraries with .vapi files)

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

Naming Conventions

Java

  • classes, interfaces, enums: CamelCase

  • methods, local variables, fields: mixedCamelCase

  • constants, enum values: UPPER_CASE

Vala

  • classes, interfaces, structs, enums, delegate types, namespaces: CamelCase

  • methods, local variables, fields, properties, signals: lower_case

  • constants, enum values: UPPER_CASE

No non-ASCII letters for identifiers allowed. You can use Vala keywords as identifiers if you prefix them with @. The at sign is not considered as part of the name.

Code Organization

Files

Java: one toplevel class per file, file name resembles class name

Vala: a Vala source file may contain multiple classes, file name doesn't need to resemble a class name

Hierarchy

Java: packages, represented by directory hierarchy, reverse domain name scheme

import javax.swing.*;

package org.foo.bar;

// ...

Vala: namespaces, not related to directory hierarchy, no reverse domain name scheme

using Gtk;

namespace Foo.Bar {
    // ...
}

Vala namespaces may contain methods without classes. They are implicitly static.

Default Import

Java: package java.lang.* imported by default

Vala: namespace GLib imported by default

Main Entry Point

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

Vala: static int main (string[] args)

May be outside a class, may be private, may return int (exit code), args argument is optional

Basic Types

  • sizes of standard types (int, long, ...) are architecture dependent. Get size of a type in bytes with sizeof (), e.g. sizeof (int)

  • additional Vala types int8, int16, int32, int64 (signed), uint8, uint16, uint32, uint64 (unsigned) with architecture independent guaranteed sizes

  • no byte (use uint8, int8 instead)

  • bool instead of boolean

  • additional basic type: unichar, representing a Unicode character

Constant modifier: const instead of final.

Vala's basic types have methods, e.g.

int a = -4.abs ();
string s = a.to_string ();
int b = int.max (5, 7);      // static method call on 'int'

Strings

Java

Data type: String

Equality test: str1.equals(str2)

Vala

Data type: string (lower case)

Equality test: str1 == str2

String comparisons compare content, not reference. You can compare strings lexicographically with <, >, <=, >= etc. Strings can be used with switch.

Vala strings are UTF-8 encoded.

Additional Vala String Features

Vala supports verbatim strings: """..."""

string verbatim = """Verbatim strings don't evaluate escape sequences
like \n, \t, ... and may span multiple lines. The line breaks are part
of the string. You can use quotation marks (") and backslashes (\)
inside a verbatim string without escaping them."""

Vala supports string templates: @"...". String templates may contain expressions, prefixed by a $ sign.

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

Arrays

Dynamic Growth

You can add elements to arrays dynamically by using the += operator. The array will be reallocated with sizes of powers of two:

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

No Boundary Checking

However, there is no runtime boundary checking for arrays in Vala:

int[] a = new int[10];
a[20] = 1;  // not safe!

(Optional boundary checking is planned for a future version of Vala.)

Multi-Dimensional Arrays

Java: jagged multi-dimensional arrays [][] (arrays of arrays)

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

Vala: rectangular multi-dimensional arrays [,], [,,], etc. (allocated as one contiguous memory block), jagged array support planned

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

Illustration: rectangular vs. jagged multi-dimensional array

multidimensional-arrays.png

Type Inference

Vala supports a mechanism called type inference (implicit typing) for local variables: Local variables may be declared using the var keyword instead of the type name if the compiler can deduce (infer) the type from the initial assignment. This helps avoiding unnecessary redundancy and is especially useful for generic types. Examples:

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

instead of

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

Still, everything is statically typed.

Foreach

Java: for (int i : numbers) { }

Vala: foreach (int i in numbers) { }

Inheritance

Java: extends, implements

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

Vala: colon followed by comma separated list, both for super class and interfaces

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

super is called base in Vala.

Object Base Class

Java: implicit inheritance from Object (java.lang.Object)

public class Foo {
    // ...
}

Vala: no implicit inheritance from Object (GLib.Object)

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

What happens if you don't inherit from Object? Nothing terrible. These classes will be slightly more lightweight, however, they will lack some features such as property change notifications, and your objects won't have a common base class. Usually inheriting from Object is what you want.

Method Overloading

Java

public class Demo {

    public void draw(String text) { }

    public void draw(Shape shape) { }


    /* Method overloading + chaining for convenience methods with less arguments */

    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: no method overloading, use different names instead or default values for arguments

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 does not support method overloading because libraries written in Vala are intended to be usable by C programmers as well with meaningful function names.

Multiple Constructors

Java: constructor overloading

public class Foo {
    public Foo() { }
    public Foo(int foo) { }
    public Foo(String bar) { }
}

new Foo();
new Foo(42);
new Foo("hello");

Vala: named constructors instead of constructor overloading

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");

Constructor Chaining

Java: this()

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

    public Foo(string bar) {
    }
}

Vala: this() or this.name_addition()

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

    public Foo.with_bar (string bar) {
    }
}

Overriding

Java: all methods are virtual (overridable) by default, final prevents overriding

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: all methods are non-virtual (not overridable) by default, overriding must be explicitly allowed with virtual. So it's the other way round. Vala has override keyword instead of @Override annotation, and it's not 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

Java

Vala

public

public

protected

protected

package-private (default)

internal

private

private (default)

Although private is default you may use it explicitly for symmetry reasons with regard to public.

Interfaces

Java: interface methods are implicitly abstract

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

Vala: abstract explicitly necessary

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

Why? Because Vala interfaces may have non-abstract methods (i.e. methods with implementations)! This means Vala interfaces can be used as mixins (restricted form of multiple inheritance).

Vala interfaces may have static methods, e.g. factory methods.

Java: interface inheritance

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 prerequisites

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 () { }
}

Interfaces in Vala may not inherit from other interfaces, but they may declare other interfaces to be prerequisites, which works in roughly the same way. Interfaces may also have a class as a prerequisite. This is often used to ensure that an instance of an interface is also an Object subclass. The fact that interfaces can not inherit from other interfaces is mostly only a technical distinction - in practice Vala's system works the same as Java in this area, but with the extra feature of prerequsite classes.

Enums

Java: enums are class based

Vala: enums are integer based. Methods allowed, however no constructors, fields, etc.

enum Season {
    SPRING,
    SUMMER,
    AUTUMN,
    WINTER;

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

Run-Time Type Information

Dynamic Type Check

Java: obj instanceof Foo

Vala: obj is Foo

Dynamic Type Casting

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

Vala: Foo foo = obj as Foo

Of course, "(obj is Foo) ? (Foo) obj : null" would do as well.

Getting Type Information

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

Java: finalizers, not deterministic

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

Vala: destructors, deterministic

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

Annotations

Java: @Annotations, self-definable

Vala: attributes, built into the compiler. Syntax: [AttributeName (param1 = value, param2 = value)]. Mostly used for bindings or D-Bus interfaces. The most prominent attribute for bindings is [CCode (...)]

Properties

Java: Bean convention, getX() and setX() methods

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: language support for properties, get {} and set {} blocks, can be accessed like fields

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++;
}

Or even shorter for the standard implementation:

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

Delegates, Closures

Java: implement delegate pattern, use anonymous inner classes

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: language support for delegates and 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);     // invoke delegate
    foo (deleg);          // pass delegate to a method
}

Closures are anonymous methods that capture the variables of the outer scope. They can be assigned to delegate variables or be passed as delegate parameters to methods.

In Java closures can be simulated with anonymous inner classes. However, anonymous inner classes can only capture final variables of the outer scope, whereas Vala closures can capture any variable. Closure support is potentially planned for Java 7.

You can assign methods directly to delegate variables:

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);
}

This means methods can be stored in variables and be passed around like objects.

Notification

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: signals (signal keyword, .connect() and .disconnect())

public class MyButton : Object {

    public signal void clicked ();

    public void test () {
        clicked ();          // emit 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 Change Notification

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: Subclasses of Object have a notify 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";
}

However, you can't get the old value.

If you're only interested in change notifications of a single property you can use this syntax:

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

Change notifications can be disabled with a CCode attribute tag immedietely before the declaration of the property:

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

Java: class-based 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 are called errors, not class-based, no wrapping

// error domain with multiple error codes instead of exception classes
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!");
}

// must be caught or propagated, compiler warning if ignored
try {
    method ();
} catch (TemperatureError e) {
    stderr.printf ("Error: %s\n", e.message);
}

Although the compiler emits warnings for ignored errors it does not abort the compilation process. This allows prototyping without proper error handling and will hopefully prevent forgotten empty catch blocks.

You can check the error code with is:

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

Parameter Directions

Vala methods can have so-called out or ref arguments. If a method argument is marked as out or ref argument in the method signature it means that the method can change the value of the passed variable (only variables can be passed as out or ref arguments) and the change is still in effect after the method returns. If the passed variable is of a reference type the method can change the reference itself (assign a whole new object to the variable instead of just changing the state of the passed object).

The difference between out and ref is that a variable passed as ref argument must be initialized before it is passed to the method, while a variable passed as out argument can be uninitialized and is expected to be initialized by the method.

The keywords must be used both at the method definition and when calling the method.

/*
 * This method takes a normal argument, an 'out' argument
 * and a 'ref' argument.
 */
void my_method (int a, out int b, ref int c) {
    a = 20;  // will have no effect outside of this method

    // until now 'b' is considered uninitialized
    b = 30;  // initialize 'b', will affect the passed variable

    c = 40;  // will affect the passed variable
}

void main () {
    int x = 2
    int y;      // may be uninitialized
    int z = 4;  // must be initialized before it is passed as 'ref' argument
    my_method (x, out y, ref z);
    stdout.printf ("%d %d %d\n", x, y, z);  // => "2 30 40"
    // 'x' is still the same, 'y' and 'z' have changed
}

Nullability

In Vala you must mark reference type parameters of methods as nullable with a question mark (?) if it should be allowed to pass null, e.g.

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)
}

This is checked both at run-time and partially at compile time and helps preventing null pointer dereferencing.

You can enable (experimental) strict nullability checking with --enable-experimental-non-null. Then Vala will check all reference type variables at compile time, not only method arguments. For example, this example won't compile with strict nullability checking enabled:

void main () {
    string? a = "hello";
    string b = a;        // Error: 'a' could be null and 'b' is not nullable
}

However, if you cast the nullable variable into a non-nullable variable with (!) it will compile:

void main () {
    string? a = "hello";
    string b = (!) a;
}

There are experiments with non-null types (via @NonNull annotations) for Java as well, e.g. JACK and JastAdd

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: reference type parameters are implicitly checked for null unless they are marked nullable with ?, so you don't have to check them manually. Methods may have preconditions:

void method (double d, int i, Foo foo)
     requires (d >= 0.0 && d <= 1.0)
     requires (i >= 0 && i <= 10)
{
    // ...
}

Vala additionally supports postconditions, for example for checking the return value:

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

result is a special variable representing the return value.

Use exceptions (errors) for recoverable runtime errors (database errors, I/O errors), use preconditions and assertions (assert (...)) for programming errors such as illegal arguments.

Structs

A struct is a concept not available in Java. To understand the difference between a struct and a class we will look at two implementations of a Point type, once as class and once as struct:

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);
    }
}

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);
    }
}

As you can see, the only difference is the struct keyword instead of class. However, struct types have different semantics than class types:

// Class
var p1 = new Point (2, 4);  // will allocate p1 on the heap
var p2 = p1;                // assignment by reference
p2.x = 3;
p1.print ();                // => (3, 4)   p1 changed as well
p2.print ();                // => (3, 4)
var p3 = new Point (3, 4);
p2 == p3;                   // => false (same values, but different references)

// Struct
var p1 = Point (2, 4);      // will allocate p1 on the stack
var p2 = p1;                // copied
p2.x = 3;
p1.print ();                // => (2, 4)   p1 did not change
p2.print ();                // => (3, 4)
var p3 = Point (3, 4);
p2 == p3;                   // => true (same values)

Structs are not allocated on the heap (that's why the new keyword is not used for the creation of structs). The most important difference is that structs are copied on assignment. They are value types, not reference types, i.e. they basically behave like int, double, etc.

Structs don't support inheritance and signals, and they can't implement interfaces.

Synchronizing

Java: synchronized

Vala: lock, cannot be applied to whole methods, only to member objects

Conditional Compilation

Java: no conditional compilation

Vala: support for simple conditional compilation with #if, #elif, #else, #endif. However, this is not a macro preprocessor like the C preprocessor.

See Conditional Compilation Example

Memory Management

Java: Garbage collection

Vala: Automatic reference counting

This has both advantages and disadvantages. Reference counting is deterministic, but you can form reference cycles in some cases. In these cases you must use weak references in order to break those cycles. The Vala keyword for this is weak.

See Vala's Memory Management Explained

Static Initialization

Java: static initializer block, called before the first instance is created or any static members are referenced

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

Vala: static construct { } block. The first time that a class, or any subclass of it, is instantiated, this code is run. It is guaranteed that this code will run exactly once in a program where such a class is used.

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 ();
    // ...
}

For more information, see the general Vala Tutorial. Type-safe varargs planned with params keyword.

Native Methods

Java: native keyword, JNI

Vala: all method calls are "native" calls. Bind C functions quickly with extern keyword or write a .vapi file. Use CCode attribute to specify the original function name (only if it differs from the Vala name)

public class MainClass : Object {

    [CCode (cname = "SampleMethod")]
    public static extern int sample_method (int x);

    static void main () {
        stdout.printf ("sample_method () returns %d\n", sample_method (5));
    }
}

Pass library name to the compiler with -X -l... (with -X meaning the next option is passed through to the C compiler)

$ valac demo.vala -X -lfoo

You can also pass a C source file containing the external method to the Vala compiler. This allows for mixed Vala and C source code projects.

$ valac demo.vala foo.c

Not Available

  • 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 strictfp, transient keywords

Features Not Covered In This Tutorial

  • Asynchronous methods
  • Alternative construction scheme (gobject-style)

See the general Vala tutorial for more information on these.

Collections

Java: java.util.* package

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

See Gee Examples, Gee Documentation

Vala allows array-like access for Gee collections (e.g. my_map[key] is equivalent to my_map.get (key)). Vala supports an in operator for collections: x in my_collection is equivalent to my_collection.contains (x). This operator also works with strings, even though strings are not collections.

Please note that Libgee checks for errors like the bounds for the index key with an assert, and so it won't raise any catchable RuntimeException like Java does.

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 Examples, GIO 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);

From Swing to GTK+

Simple 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: Box, Table, Fixed, ...)

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

你可能感兴趣的:(Vala)