Programming in D for Java Programmers

From D Wiki
Jump to: navigation, search

Hello World

Assuming you've downloaded a D compiler, a basic "hello world" program will look like this:

1 // hello.d
2 import std.stdio;
3 
4 void main(string[] args)
5 {
6    writeln("Hello, world!");
7 }

If you're using DMD, you can run dmd -run hello.d to compile and execute the program.

There are two main differences from a "hello world" in Java. First, there is no need for a class. In D, functions can exist at the top-level, inside a class or struct as a method, and even inside another function. The only requirement (without abusing features of D) is that the main function is located at the top-level.

This isn't the only way to define main; the following will work as well:

  • void main() {}
  • int main() { return 0; }
  • int main(string[] args) { return 0; }

Using void as the return type means a successful run of the program exits with 0[1].

Downcasting

The Java way

if (animal instanceof Cat)
{
    Cat cat = (Cat) animal;
    /* use cat */
}

The D way

if(auto cat = cast(Cat) animal)
{
    /* use cat */
}

Static Class Member Variables

In Java if you declare a member variable as static it will be stored in global storage for the entire program, allowing you to access the same reference from multiple threads.

 1 class Person {
 2    public String firstName;
 3 
 4    public Person(String fname) {
 5       this.firstName = fname;
 6    }
 7 }
 8 
 9 class ProgramState {
10    public static Person person;
11 
12    static {
13       person = new Person("Jessie");
14    }
15 }
16 
17 public class Program {
18 
19    public static void main(String[] args) throws Exception {
20       new ProgramState();
21       Thread secondThread = new Thread(new Runnable() {
22          @Override
23          public void run() {
24             ProgramState.person.firstName = "James";
25          }
26       });
27       System.out.println(ProgramState.person.firstName); // => Jessie
28       secondThread.start();
29       secondThread.join();
30       System.out.println(ProgramState.person.firstName); // => James
31    }
32 }

A static member variable in D is local to the current thread only, known as thread-local storage. Every thread you create will have a different version of your static member variables. To have the same behaviour as Java in D, you need to use the __gshared type qualifier.

 1 import core.thread;
 2 
 3 class Person
 4 {
 5    string firstName;
 6 
 7    this(string fname) {
 8       firstName = fname;
 9    }
10 }
11 
12 class ProgramState
13 {
14    __gshared static Person person;
15 
16    static this()
17    {
18       person = new Person("Jessie");
19    }
20 }
21 
22 void main()
23 {
24    new ProgramState();
25    Thread secondThread = new Thread(() {
26       ProgramState.person.firstName = "James";
27    });
28    assert("Jessie" == ProgramState.person.firstName);
29    secondThread.start();
30    secondThread.join();
31    assert("James" == ProgramState.person.firstName, "firstName is not James");
32 }

Removing the __gshared from the above snippet will result in the second assertion failing as ProgramState.person.firstName will be "Jessie".

For an overview of the different forms of concurrency, see the Data Sharing Concurrency chapter in Programming in D which also explains one of D's preferred way of sharing variables between threads: shared.

References